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 | 441 ++-- .../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 | 184 +- .../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 | 461 +++- .../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 | 102 +- .../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, 10934 insertions(+), 1584 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 0be48dbc67..207b7a5448 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 2009cf46a3..e5c2d138da 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 573107797e..357750329a 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 int getStatementHandle() { 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 SQLitePreparedStatement(SQLiteDatabase db, String sql, boolean finalize) for (HashMap.Entry entry : hashMap.entrySet()) { FileLog.d("tmessages", "exist entry = " + entry.getValue()); } - } + }*/ } @@ -101,9 +100,9 @@ public void finalizeQuery() { 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 89992d69dc..681294e859 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 static int getViewInset(View view) { 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 be59939316..c41b14bfa9 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 void playTogether(Object... items) { 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 a4bb1c3497..4e492ceafe 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.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 @@ private HashMap readContactsFromPhoneBook() { 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 @@ private HashMap readContactsFromPhoneBook() { } 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 @@ private HashMap readContactsFromPhoneBook() { } 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 @@ private HashMap readContactsFromPhoneBook() { 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 void run() { } } - 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 void run() { 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 void run() { 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 void run() { 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 void run(TLObject response, TLRPC.TL_error error) { } 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 void run() { 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 void addContact(TLRPC.User user) { 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 void run(TLObject response, TLRPC.TL_error error) { 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 71a5e9b72f..7dd282aae8 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.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); - } - - private static void loadEmoji(final int page) { - try { + 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 { float scale; int imageResize = 1; if (AndroidUtilities.density <= 1.0f) { @@ -290,64 +295,64 @@ public void run() { 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 Rect getDrawRect() { } @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 void draw(Canvas canvas) { 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 @@ private static boolean isNextCharIsColor(CharSequence cs, int i) { 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 static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fo 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 static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fo 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 static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fo 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 3cf8e8277f..21355c5d2c 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 @@ private HashMap createMediaPaths() { } 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 273f3ba884..d7fda8509b 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.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 @@ 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 AudioBuffer(int capacity) { 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 static class SearchImage { 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 static class SearchImage { 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 static class SearchImage { 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 void onChange(boolean selfChange) { } } - /*private class GalleryObserverInternal extends ContentObserver { + private class GalleryObserverInternal extends ContentObserver { public GalleryObserverInternal() { super(null); } @@ -367,9 +400,13 @@ public GalleryObserverInternal() { @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 GalleryObserverExternal() { @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 void run() { 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 void run() { } } } + 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 MediaController() { 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 MediaController() { 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 void onReceive(Context context, Intent intent) { } 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 void onReceive(Context context, Intent intent) { 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 void onReceive(Context context, Intent intent) { }; } - /*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 void onReceive(Context context, Intent intent) { 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 @@ private void stopProgressTimer() { } 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 void cleanup() { videoDownloadQueue.clear(); downloadQueueKeys.clear(); videoConvertQueue.clear(); + playlist.clear(); + shuffledPlaylist.clear(); typingTimes.clear(); cancelVideoConvert(null); } @@ -652,7 +702,7 @@ public void checkAutodownloadSettings() { } } 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 void checkAutodownloadSettings() { } } 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 void checkAutodownloadSettings() { } } 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 void checkAutodownloadSettings() { } } 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 boolean canDownloadMedia(int type) { 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 @@ protected void processDownloadObjects(int type, ArrayList object 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 @@ private void processLaterArrays() { 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 void didReceivedNotification(int id, Object... args) { } 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 void didReceivedNotification(int id, Object... args) { 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 void didReceivedNotification(int id, Object... args) { 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 void didReceivedNotification(int id, Object... args) { } } 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 void run() { audioTrackPlayer.setNotificationMarkerPosition(1); } if (finalBuffersWrited == 1) { - clenupPlayer(true); + clenupPlayer(true, true); } } } @@ -1221,7 +1289,7 @@ public void onSensorChanged(SensorEvent event) { 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 @@ private void startProximitySensor() { } } - 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 @@ private void clenupPlayer(boolean notify) { 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 boolean seekToProgress(MessageObject messageObject, float progress) { 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 boolean playAudio(MessageObject messageObject) { } 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 boolean playAudio(MessageObject messageObject) { } } 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 void run() { audioTrackPlayer.setPlaybackPositionUpdateListener(new AudioTrack.OnPlaybackPositionUpdateListener() { @Override public void onMarkerReached(AudioTrack audioTrack) { - clenupPlayer(true); + clenupPlayer(true, true); } @Override @@ -1420,7 +1668,9 @@ public void onPeriodicNotification(AudioTrack audioTrack) { }); 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 void onPeriodicNotification(AudioTrack audioTrack) { audioTrackPlayer = null; isPaused = false; playingMessageObject = null; + downloadingCurrentMessage = false; } return false; } @@ -1440,13 +1691,28 @@ public void onPeriodicNotification(AudioTrack audioTrack) { 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 void onCompletion(MediaPlayer mediaPlayer) { audioPlayer = null; isPaused = false; playingMessageObject = null; + downloadingCurrentMessage = false; } return false; } @@ -1463,6 +1730,7 @@ public void onCompletion(MediaPlayer mediaPlayer) { lastProgress = 0; lastPlayPcm = 0; playingMessageObject = messageObject; + NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioDidStarted, messageObject); if (audioPlayer != null) { try { @@ -1484,7 +1752,7 @@ public void onCompletion(MediaPlayer mediaPlayer) { 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 void run() { }); } + 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 void stopAudio() { } 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 boolean pauseAudio(MessageObject messageObject) { 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 boolean resumeAudio(MessageObject messageObject) { 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 boolean resumeAudio(MessageObject messageObject) { checkPlayerQueue(); } isPaused = false; + NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioPlayStateChanged, playingMessageObject.getId()); } catch (Exception e) { FileLog.e("tmessages", e); return false; @@ -1579,15 +1907,23 @@ public boolean resumeAudio(MessageObject messageObject) { } 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 void startRecording(final long dialog_id, final MessageObject reply_to_ms 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 void run() { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { + recordStartRunnable = null; NotificationCenter.getInstance().postNotificationName(NotificationCenter.recordStartError); } }); @@ -1653,6 +1991,7 @@ public void run() { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { + recordStartRunnable = null; NotificationCenter.getInstance().postNotificationName(NotificationCenter.recordStartError); } }); @@ -1663,11 +2002,12 @@ public void run() { 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 void run() { } 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 void run() { 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 void run() { } } - 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 static boolean isWebp(Uri uri) { 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 48aaa26512..7569f9cb00 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 MessageObject(TLRPC.Message message, AbstractMap use } 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 MessageObject(TLRPC.Message message, AbstractMap use } 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 MessageObject(TLRPC.Message message, AbstractMap use 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 void generateCaption() { 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 static boolean isStickerMessage(TLRPC.Message message) { 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 int getApproximateHeight() { 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 boolean isSticker() { 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 156d4b38c4..6bcaf3359c 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 void run() { } 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 b5030041b5..ad37757fcf 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 void run() { }); } - 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 @@ private void updateDialogsWithReadedMessagesInternal(final ArrayList me 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; - } - dialogsToUpdate.put((long) entry.getKey(), count); - if (dialogsToReload.length() != 0) { - dialogsToReload.append(","); + if (count != 0) { + dialogsToUpdate.put((long) entry.getKey(), count); + if (dialogsToReload.length() != 0) { + dialogsToReload.append(","); + } + dialogsToReload.append(entry.getKey()); } - dialogsToReload.append(entry.getKey()); } cursor.dispose(); } @@ -1231,7 +1230,7 @@ private void updateDialogsWithReadedMessagesInternal(final ArrayList me } } - 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 void updateDialogsWithReadedMessages(final HashMap inbo 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 void run() { 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 0000000000..eb129930e8 --- /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 0000000000..6201d7e08c --- /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 ffaf321a67..474d0c7705 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 3283523ab8..5983c38556 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.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 @@ private void showOrUpdateNotification(boolean notifyAboutLast) { } 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 @@ private void showOrUpdateNotification(boolean notifyAboutLast) { continue; } if (i == 0) { - lastMessageFull = message; - lastMessage = lastMessageFull; + lastMessage = message; } if (pushDialogs.size() == 1) { if (replace) { @@ -692,9 +686,6 @@ private void showOrUpdateNotification(boolean notifyAboutLast) { showExtraNotifications(mBuilder, notifyAboutLast); notificationManager.notify(1, mBuilder.build()); - if (preferences.getBoolean("EnablePebbleNotifications", false)) { - sendAlertToPebble(lastMessageFull); - } scheduleNotificationRepeat(); } catch (Exception e) { @@ -897,26 +888,6 @@ private void dismissNotification() { } } - 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 060d21799a..230497db88 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.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 void sendMessage(ArrayList messages, long peer) { 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 @@ private static boolean prepareSendingDocumentInternal(String path, String origin return false; } MimeTypeMap myMime = MimeTypeMap.getSingleton(); + TLRPC.TL_documentAttributeAudio attributeAudio = null; if (uri != null) { String extension = null; if (mime != null) { @@ -1885,8 +1890,31 @@ private static boolean prepareSendingDocumentInternal(String path, String origin 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 @@ private static boolean prepareSendingDocumentInternal(String path, String origin 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 static void prepareSendingDocument(String path, String originalPath, Uri 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 1fe80d0396..7a0ad4ff7c 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 static String getUserName(TLRPC.User user) { 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 static String getFirstName(TLRPC.User user) { 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 0000000000..19e16415fb --- /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 0000000000..82d3f6458d --- /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 0000000000..7b99fe8125 --- /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 0000000000..66e8050d8f --- /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 0000000000..caacb25107 --- /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 0000000000..c43a85e62f --- /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 0000000000..1ca33999a9 --- /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 0000000000..2a4ba062e9 --- /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 0000000000..4d9d5c696b --- /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 0000000000..1321f14773 --- /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 0000000000..c1187911fc --- /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 0000000000..7d25ff403a --- /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 0000000000..a7490e1acb --- /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 0000000000..222e65fb66 --- /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 0000000000..d2431cd05a --- /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 0000000000..2b9abf2e25 --- /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 0000000000..60f7ba6798 --- /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 0000000000..9a2a616b0e --- /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 0000000000..f27aa81121 --- /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 0000000000..ad29d61854 --- /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 0000000000..7c4dbef5f5 --- /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 f1acd02851..492fea8d92 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 void run() { } }); } + + 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 688e032c80..c8bb6d3e98 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 @@ private void addToData(int index, T item) { 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 3b4c28c1a7..d56fb0b998 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 @@ 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 bbbc20a54f..0d7e11af74 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 @@ 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 790bf06f8b..37453d67c2 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.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 c431b61499..b91274a1e2 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 @@ View next(RecyclerView.Recycler recycler) { 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 a52bbffe5d..a0508ad5f4 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.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 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 LinearLayoutManager(Context context) { * @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 boolean getReverseLayout() { * 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 View findViewByPosition(int position) { 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 @@ private boolean updateAnchorFromPendingData(RecyclerView.State state, AnchorInfo } // 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 void scrollToPosition(int position) { * 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 @@ private void recycleChildren(RecyclerView.Recycler recycler, int startIndex, int /** * 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 @@ private void recycleViewsFromStart(RecyclerView.Recycler recycler, int dt) { /** * 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 @@ private void recycleViewsFromEnd(RecyclerView.Recycler recycler, int dt) { * @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 boolean supportsPredictiveItemAnimations() { 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 3d56822f72..05d0e93a97 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 @@ private void swapMoveOp(List list, int badMove, int next) { } 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 @@ void swapMoveRemove(List list, int movePos, UpdateOp moveOp, 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 @@ void swapMoveRemove(List list, int movePos, UpdateOp moveOp, } 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 @@ private void swapMoveAdd(List list, int move, UpdateOp moveOp, int add } 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 @@ private int getLastMoveOutOfOrder(List list) { 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 b97bd5a657..15a41191d2 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 @@ static int binarySearch(int[] array, int size, int value) { 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 f6a17a1d8f..4aa003c754 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.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.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.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 @@ *

* 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 void run() { 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 void run() { 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 RecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) 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 void setAccessibilityDelegateCompat( 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 int getBaseline() { } } + /** + * 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 @@ private void setScrollState(int state) { 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 void addItemDecoration(ItemDecoration decor) { 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 void removeItemDecoration(ItemDecoration decor) { 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 void scrollBy(int x, int y) { 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 @@ private void consumePendingUpdateOperations() { * * @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 @@ boolean scrollByInternal(int x, int y, boolean fromMotionEvent, int motionX, int 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 boolean fling(int velocityX, int velocityY) { "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 @@ private void stopScrollersInternal() { } } + /** + * 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 @@ protected void onDetachedFromWindow() { 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 @@ void assertNotInLayoutOrScroll(String message) { * 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 boolean onInterceptTouchEvent(MotionEvent e) { 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 boolean onInterceptTouchEvent(MotionEvent e) { case MotionEvent.ACTION_UP: { mVelocityTracker.clear(); + stopNestedScroll(); } break; case MotionEvent.ACTION_CANCEL: { @@ -1883,6 +2085,16 @@ public boolean onInterceptTouchEvent(MotionEvent e) { 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 boolean onTouchEvent(MotionEvent e) { } 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 boolean onTouchEvent(MotionEvent e) { 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 boolean onTouchEvent(MotionEvent e) { if (!((xvel != 0 || yvel != 0) && fling((int) xvel, (int) yvel))) { setScrollState(SCROLL_STATE_IDLE); } + mVelocityTracker.clear(); releaseGlows(); } break; @@ -1974,6 +2222,8 @@ public boolean onTouchEvent(MotionEvent e) { } break; } + vtev.recycle(); + return true; } @@ -1981,6 +2231,7 @@ private void cancelTouch() { if (mVelocityTracker != null) { mVelocityTracker.clear(); } + stopNestedScroll(); releaseGlows(); setScrollState(SCROLL_STATE_IDLE); } @@ -2823,6 +3074,18 @@ protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) 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 View findChildViewUnder(float x, float y) { 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 void notifyItemRangeRemoved(int positionStart, int itemCount) { } 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 @@ private void dispatchChildAttached(View child) { * 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 boolean performAccessibilityActionForItem(Recycler recycler, State state, 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 void getItemOffsets(Rect outRect, View view, RecyclerView parent, State s * 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 interface OnItemTouchListener { * 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 interface OnItemTouchListener { * 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 interface RecyclerListener { 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 @@ private int getAdapterPositionFor(ViewHolder viewHolder) { 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 @@ private static class ItemHolderInfo { 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 d28434a609..166311dab9 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 boolean getReverseLayout() { @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { ensureOrientationHelper(); - final AnchorInfo anchorInfo = mAnchorInfo; anchorInfo.reset(); @@ -577,21 +576,22 @@ public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State 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 @@ private void fixStartGap(RecyclerView.Recycler recycler, RecyclerView.State stat } } - 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; - } - 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(); - } + // Line of the furthest row. + final boolean clipToPadding = getClipToPadding(); + if (clipToPadding) { + mLayoutState.mStartLine = mPrimaryOrientation.getStartAfterPadding() - startExtra; + mLayoutState.mEndLine = mPrimaryOrientation.getEndAfterPadding() + endExtra; } else { - mLayoutState.mExtra = 0; + mLayoutState.mEndLine = mPrimaryOrientation.getEnd() + endExtra; + mLayoutState.mStartLine = -startExtra; } - 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 @@ private int fill(RecyclerView.Recycler recycler, LayoutState layoutState, 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 @@ private int fill(RecyclerView.Recycler recycler, LayoutState layoutState, } 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 @@ private void attachViewToSpans(View view, LayoutParams lp, LayoutState layoutSta } } - 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 @@ private void updateRemainingSpans(Span span, int layoutDir, int targetLine) { 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 @@ private int getMinEnd(int def) { } 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 @@ private void recycleFromEnd(RecyclerView.Recycler recycler, int line) { 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 void scrollToPositionWithOffset(int position, int offset) { 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 0000000000..c3ab9bd3cb --- /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 0000000000..22cb8061b0 --- /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 0000000000..63a492beb0 --- /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 44ddd667ef..2457f49323 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 c7b0937a63..575d1e2178 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 void run() { 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 928d5e5724..3f1dafe5b9 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 void run() { 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 void run() { 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 2a006d37b6..e7268e2ba1 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 @@ private static class RequestInfo { 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 @@ private static class RequestInfo { 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 void start() { 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 void run() { }); return; } - Long mediaId = null; String fileNameFinal; String fileNameTemp; String fileNameIv = null; @@ -223,7 +225,7 @@ public void run() { 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 @@ private void processRequestResult(RequestInfo requestInfo, TLRPC.TL_error error) } } - 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 @@ private void processRequestResult(RequestInfo requestInfo, TLRPC.TL_error error) 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 @@ private void startDownloadRequest() { 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 2860c3cc99..19ebeba037 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 static TLRPC.PhotoSize getClosestPhotoSizeWithSize(ArrayList= 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 TextView addSubItem(int id, String text, int icon) { 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 void onDispatchKeyEvent(KeyEvent keyEvent) { @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 boolean onKey(View v, int keyCode, KeyEvent event) { } }); } + processedPopupClick = false; popupWindow.setFocusable(true); if (popupLayout.getMeasuredWidth() == 0) { updateOrShowPopup(true, true); @@ -367,6 +373,11 @@ public ActionBarMenuItem setIsSearchField(boolean value) { 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 ActionBarMenuItem setIsSearchField(boolean value, boolean needClearButton 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 void afterTextChanged(Editable s) { 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 @@ private void updateOrShowPopup(boolean show, boolean update) { } } + if (show) { + popupLayout.scrollToTop(); + } + if (subMenuOpenSide == 0) { if (showFromBottom) { if (show) { @@ -574,10 +590,6 @@ public void hideSubItem(int id) { 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 void showSubItem(int id) { 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 7d6816f25d..ee42b1eb97 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.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 interface OnDispatchKeyEventListener { 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 static class ActionBarPopupWindowLayout extends LinearLayout { 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 void setBackScaleX(float value) { 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 void setBackScaleY(float value) { } } 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 @@ private void startChildAnimation(View child) { } } + @Override + public void addView(View child) { + linearLayout.addView(child); + } + public float getBackScaleX() { return backScaleX; } @@ -183,6 +205,18 @@ protected void onDraw(Canvas canvas) { 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 void startAnimation() { 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 dad03f246e..1138a158b8 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.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 BaseFragment(Bundle args) { 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 dd00b928bb..87ac403bae 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 @@ 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 void setTextAndIcon(CharSequence text, int icon) { 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 @@ protected void onCreate(Bundle savedInstanceState) { 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)); + + 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); + } + } - LinearLayout containerView = new LinearLayout(getContext()); - containerView.setBackgroundColor(0xffffffff); + @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 void onClick(View v) { 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(); - } - } + if (Build.VERSION.SDK_INT >= 21) { + startOpenAnimation(); + } + } + }); + } - @Override - public void onAnimationEnd(Animator animation) { - if (delegate != null) { - delegate.onOpenAnimationEnd(); - } - } + @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(); + } + } - @Override - public void onAnimationCancel(Animator animation) { + 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; + } - @Override - public void onAnimationRepeat(Animator animation) { + @SuppressLint("NewApi") + private void startRevealAnimation(final boolean open) { - } - }); - 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 (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()); + } - 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); + 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 FrameLayout getContainer() { } public LinearLayout getSheetContainer() { - return linearLayout; + return containerView; } public int getTag() { @@ -397,13 +574,14 @@ public void setItemText(int item, CharSequence text) { 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 void dismiss() { 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 Builder setTag(int tag) { 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 Builder setIsGrid(boolean value) { 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 ce43585ccb..d9c26a0a2c 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 void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { @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 void requestLayout() { @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 8c39b844a2..8efc34296c 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 void run() { 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 d1f497b7bc..102a170fc3 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 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 Holder(View itemView) { 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 void setDelegate(PhotoAttachAdapterDelegate photoAttachAdapterDelegate) { 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 00206cf9b7..28864d911f 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 @@ private boolean checkStickerFilesExistAndDownload() { } 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 0000000000..99ff51b60a --- /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 0000000000..a663665bb1 --- /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 1c1699d13f..990286990b 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.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 void onFragmentDestroy() { } @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 0000000000..d2e9b0c1f5 --- /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 6c05ae107a..32d9c6baa8 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 void setText(String text) { 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 boolean onTouchEvent(MotionEvent event) { 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 @@ protected void onDraw(Canvas canvas) { 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 12c7492227..82ab4b7307 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 boolean onTouchEvent(MotionEvent event) { 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 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 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 1b7a9db994..77f5069e21 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 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 ChatAudioCell(Context context) { seekBar = new SeekBar(context); seekBar.delegate = this; - progressView = new ProgressView(); + radialProgress = new RadialProgress(this); drawForwardedName = true; if (timePaint == null) { @@ -78,7 +79,7 @@ protected void onDetachedFromWindow() { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - updateButtonState(); + updateButtonState(false); } @Override @@ -131,21 +132,25 @@ private void didPressedButton() { } 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 void updateProgress() { } 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 void downloadAudioIfNeed() { 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 void updateButtonState() { } 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 void updateButtonState() { @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 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto 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 void setMessageObject(MessageObject messageObject) { 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 @@ protected void onDraw(Canvas canvas) { } 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 8e28d51634..dda180c9a6 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 void setMessageObject(MessageObject messageObject) { 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 129348b605..92c337c27f 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 boolean onTouchEvent(MotionEvent event) { 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 23f72ec768..0c704b9564 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 @@ private void didClickedImage() { 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 aac1b324da..14159564f7 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 boolean onTouchEvent(MotionEvent event) { 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 void setMessageObject(MessageObject messageObject) { 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 0000000000..d85fe7747f --- /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 b163ec9188..73ac7d0632 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 void buildLayout() { 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 void buildLayout() { 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 void buildLayout() { 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 void buildLayout() { 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 54414ebc22..c389b017d2 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.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 PhotoAttachCameraCell(Context context) { 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 bf00964c49..9018a1623a 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 void setChecked(boolean value, boolean animated) { 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 7cc059b687..9d677bb44e 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 void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb) }); 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 void onSuccessDownload(String name) { @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 1646b509b4..010b51a0c7 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 SharedMediaSectionCell(Context context) { 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 ce803d3152..1f5c47eeb7 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 void setSticker(TLRPC.Document document, boolean showEmoji) { 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 7889b78037..7cab5ae050 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 TextDetailCell(Context context) { 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 TextDetailCell(Context context) { 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 8eb72c7e14..2addf5a7d1 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.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 boolean onFragmentCreate() { } @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 5c00884907..a71dcc505b 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.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 bc60400737..b062444185 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.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 void onFragmentDestroy() { } @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 e4077ef3b7..5144dc26df 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.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 @@ 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 0e40b1a416..0f607ee9a3 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.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 8e59129c3b..0077cde012 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.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.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.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.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.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 void run() { 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 void onFragmentDestroy() { 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 void onFragmentDestroy() { 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 View createView(Context context, LayoutInflater inflater) { lastStatus = null; hasOwnBackground = true; chatAttachView = null; + chatAttachViewSheet = null; ResourceLoader.loadRecources(context); @@ -673,7 +680,7 @@ public void onClick(DialogInterface dialogInterface, int i) { 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 void onClick(DialogInterface dialogInterface, int i) { 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 void didPressedButton(int button) { showReplyPanel(false, null, null, null, false, true); } return; + } else { + chatAttachViewSheet.dismissWithButtonClick(button); } processSelectedAttach(button); } }); - } - 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)); - } + builder.setDelegate(new BottomSheet.BottomSheetDelegate() { - @Override - public void onOpenAnimationEnd() { + @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(); + } - } - }); 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 void onClick(View v) { 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 void run() { 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 void onSearchPressed(EditText editText) { 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 void onSearchPressed(EditText editText) { 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 boolean onTouch(View v, MotionEvent event) { @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 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } 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 void needSendTyping() { @Override public void onAttachButtonHidden() { + if (actionBar.isSearchFieldVisible()) { + return; + } if (attachItem != null) { attachItem.setVisibility(View.VISIBLE); } @@ -1670,6 +1693,9 @@ public void onAttachButtonHidden() { @Override public void onAttachButtonShow() { + if (actionBar.isSearchFieldVisible()) { + return; + } if (attachItem != null) { attachItem.setVisibility(View.GONE); } @@ -1680,7 +1706,7 @@ public void onAttachButtonShow() { @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 void startDocumentSelectActivity() { }); 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 void showReplyPanel(boolean show, MessageObject messageObject, ArrayList< 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 void showReplyPanel(boolean show, MessageObject messageObject, ArrayList< 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 void showReplyPanel(boolean show, MessageObject messageObject, ArrayList< } } 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 void sendButtonPressed(int index) { 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 void run() { 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 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi 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 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi } 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 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi 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 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi 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 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi } 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 boolean onPreDraw() { 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 void createMenu(View v, boolean single) { 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 void createMenu(View v, boolean single) { 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 void createMenu(View v, boolean single) { 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 void createMenu(View v, boolean single) { 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 void createMenu(View v, boolean single) { 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 void onClick(DialogInterface dialogInterface, int i) { 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 void onClick(DialogInterface dialogInterface, int i) { 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 void onClick(DialogInterface dialogInterface, int i) { 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 void onClick(DialogInterface dialogInterface, int i) { } } } 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 void onClick(DialogInterface dialogInterface, int i) { 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 void onClick(DialogInterface dialogInterface, int i) { 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 boolean onBackPressed() { 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 void didPressUrl(String url) { 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 void didPressUrl(String url) { } } }); + } else if (viewType == 8) { + view = new ChatMusicCell(mContext); } if (view instanceof ChatBaseCell) { @@ -5261,7 +5339,7 @@ public void didPressUrl(MessageObject messageObject, String url) { 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 void didPressUrl(MessageObject messageObject, String url) { 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 void onClick(DialogInterface dialogInterface, int i) { 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 cb8164d783..a6d9877481 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 void setDelegate(BotKeyboardViewDelegate botKeyboardViewDelegate) { 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 void setButtons(TLRPC.TL_replyKeyboardMarkup buttons) { 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 void setButtons(TLRPC.TL_replyKeyboardMarkup buttons) { 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 6fc40e4a84..b939a3ec75 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.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 interface ChatActivityEnterViewDelegate { 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 void onClick(View view) { } }); - 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 boolean onKey(View view, int i, KeyEvent keyEvent) { 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 boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { } }); messageEditText.addTextChangedListener(new TextWatcher() { + boolean processChange = false; + @Override public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { @@ -247,16 +252,20 @@ public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) @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 void onTextChanged(CharSequence charSequence, int start, int before, int @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 @@ private void onWindowSizeChanged() { 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 void onAnimationEnd(Object animation) { }); 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 void onAnimationEnd(Object animation) { 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 void onAnimationEnd(Object animation) { 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,12 +902,35 @@ public void onAnimationEnd(Object animation) { if (attachButton != null) { delegate.onAttachButtonShow(); attachButton.setVisibility(View.VISIBLE); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) messageEditText.getLayoutParams(); + 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); - messageEditText.setLayoutParams(layoutParams); } } + } else { + layoutParams.rightMargin = AndroidUtilities.dp(2); } + messageEditText.setLayoutParams(layoutParams); } private void updateAudioRecordIntefrace() { @@ -1108,6 +1130,7 @@ private void updateBotButton() { } else { botButton.setVisibility(GONE); } + updateFieldRight(2); ViewProxy.setPivotX(attachButton, AndroidUtilities.dp(botButton.getVisibility() == GONE ? 48 : 96)); attachButton.clearAnimation(); } @@ -1209,12 +1232,15 @@ public void onEmojiSelected(String symbol) { 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 461e32f9b4..3b175e09ae 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.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 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 interface ChatAttachViewDelegate { 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 AttachButton(Context context) { 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 void setTextAndIcon(CharSequence text, int icon) { 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 void selectedPhotosChanged() { } }); - 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 void selectedPhotosChanged() { "" }; 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 boolean onTouch(View v, MotionEvent event) { 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 void setDelegate(ChatAttachViewDelegate chatAttachViewDelegate) { 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 HashMap getSelectedPhotos() { } 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 0000000000..3e39df2e0a --- /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 076a918696..683ad8e319 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 boolean onTouchEvent(MotionEvent ev) { 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 @@ private void onPageScrolled(int position, int width, int positionOffsetPixels) { 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 @@ private void saveRecentStickers() { 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 void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 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 0e38769e6e..3bd67919d9 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.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 EmptyTextProgressView(Context context) { 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 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { 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 aedc5bcd65..9ac490ad4e 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 void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCoun 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 60c2522ebe..74f4168a5e 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 LineProgressView(Context context) { progressPaint.setStyle(Paint.Style.STROKE); progressPaint.setStrokeCap(Paint.Cap.ROUND); progressPaint.setStrokeWidth(AndroidUtilities.dp(2)); - progressPaint.setColor(0xff36a2ee); } } @@ -70,7 +72,11 @@ private void updateAnimation() { } 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 void setProgress(float value, boolean animated) { } 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 e87f71c0c8..10b9309ae0 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 @@ private void tryComputeMaxWidth() { } 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 6321efc631..b4d4087929 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.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 PagerSlidingTabStrip(Context context) { 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 22f7a43265..1834f9cf4e 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 boolean onLongClick(View v) { @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 void onShow() { } 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 ced235b6a6..d2de9216ec 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 @@ 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 void run() { } 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 fcff6ef23b..4f0051ce5d 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 interface PhotoViewerCaptionEnterViewDelegate { private boolean keyboardVisible; private int emojiPadding; + private boolean innerTextChange; + private PhotoViewerCaptionEnterViewDelegate delegate; public PhotoViewerCaptionEnterView(Context context, SizeNotifierFrameLayoutPhoto parent) { @@ -149,6 +151,8 @@ public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { } }); messageEditText.addTextChangedListener(new TextWatcher() { + boolean processChange = false; + @Override public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { @@ -156,23 +160,31 @@ public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) @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 void onEmojiSelected(String symbol) { 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 67c72c127f..657566273a 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.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 PhotoPickerBottomLayout(Context context) { 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 PhotoPickerBottomLayout(Context context) { 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 PhotoPickerBottomLayout(Context context) { 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 void updateSelectedCount(int count, boolean disable) { 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 c6f7bb0383..d145ca2f61 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 PopupAudioView(Context context) { 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 void updateProgress() { 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 af86334cdf..8826b64a2d 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 RadialProgress(View parentView) { progressPaint.setStyle(Paint.Style.STROKE); progressPaint.setStrokeCap(Paint.Cap.ROUND); progressPaint.setStrokeWidth(AndroidUtilities.dp(2)); - progressPaint.setColor(0xffffffff); } parent = parentView; } @@ -86,7 +86,7 @@ private void updateAnimation() { } public void setProgressColor(int color) { - progressPaint.setColor(color); + progressColor = color; } public void setHideCurrentDrawable(boolean value) { @@ -154,6 +154,7 @@ public void onDraw(Canvas canvas) { 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 b356c71961..f503341e19 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 void run() { 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 a5b56b4d35..9b4ce1c41b 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.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 ScrollSlidingTabStrip(Context context) { 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 bc15136a03..727b3bacbf 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 @@ 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 interface SeekBarDelegate { 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 interface SeekBarDelegate { 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 boolean isDragging() { } 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 0000000000..c64b07616f --- /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 fa6740a9d6..b57b218945 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 @@ protected void onDraw(Canvas canvas) { 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 7bfd47999d..1aae159963 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 TimerDrawable(Context context) { 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 void setTime(int value) { 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 d644d7d6d9..f26e450f8f 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 void stop() { @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 d562cc6bb9..980237dfcb 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 @@ protected Bitmap doInBackground(Integer... objects) { 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 d794f29dbb..e42fe5ae4c 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 WebFrameLayout(Context context, BottomSheet parentDialog, String title, S 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 boolean onTouch(View v, MotionEvent event) { }); 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 c09173f9d8..f57e4f9bcb 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.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 void onFragmentDestroy() { } @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 6a6695aebe..88ce8849b4 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.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 void onFragmentDestroy() { } @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 3058d69122..16e7102943 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 @@ 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 void onFragmentDestroy() { } @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 boolean onTouch(View v, MotionEvent event) { 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 53ec757dab..3362c6714a 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.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 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 void onFragmentDestroy() { } @Override - public View createView(final Context context, LayoutInflater inflater) { + public View createView(final Context context) { searching = false; searchWas = false; @@ -887,7 +886,7 @@ public void onClick(DialogInterface dialogInterface, int i) { 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 2600921826..cee01daf9b 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.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 void onFragmentDestroy() { } @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 boolean onTouch(View v, MotionEvent event) { 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 2639f756a9..a5142a02ae 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 void onFragmentDestroy() { } @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 93aaffa072..5684bc3fba 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.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 void onResume() { } @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 1ea12de423..3677a8ee9d 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.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 void onFragmentDestroy() { } @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 fea96db4c2..b75c2d3669 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 @@ 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 boolean onFragmentCreate() { } @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 void onItemClick(int id) { } }); - 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 96fc7648fb..be68ecf575 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.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 1b1f81c049..2ac98eb9f8 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.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 void onFragmentDestroy() { } @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 b476860fca..7b5950b6fa 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.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 void onFragmentDestroy() { } @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 e77c865dc0..7e9980499d 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.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.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.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 void onClick(View v) { 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 void onItemClick(AdapterView parent, View view, int position, long id) } }); + 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 void onItemClick(AdapterView parent, View view, int position, long id) 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 @@ private boolean handleIntent(Intent intent, boolean isNew, boolean restore, bool Integer push_enc_id = 0; Integer open_settings = 0; boolean showDialogsList = false; + boolean showPlayer = false; photoPathsArray = null; videoPath = null; @@ -589,7 +604,6 @@ private boolean handleIntent(Intent intent, boolean isNew, boolean restore, bool } 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 @@ private boolean handleIntent(Intent intent, boolean isNew, boolean restore, bool } else { showDialogsList = true; } + } else if (intent.getAction().equals("com.tmessages.openplayer")) { + showPlayer = true; } } } @@ -801,6 +817,30 @@ private boolean handleIntent(Intent intent, boolean isNew, boolean restore, bool } 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 @@ private boolean handleIntent(Intent intent, boolean isNew, boolean restore, bool 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 @@ private boolean handleIntent(Intent intent, boolean isNew, boolean restore, bool } } else { if (actionBarLayout.fragmentsStack.isEmpty()) { - actionBarLayout.addFragmentToStack(new MessagesActivity(null)); + actionBarLayout.addFragmentToStack(new DialogsActivity(null)); drawerLayoutContainer.setAllowOpenDrawer(true, false); } } @@ -861,7 +901,7 @@ private boolean handleIntent(Intent intent, boolean isNew, boolean restore, bool 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 void run() { 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 @@ protected void onNewIntent(Intent intent) { } @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 boolean onKeyUp(int keyCode, KeyEvent event) { 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 boolean needPresentFragment(BaseFragment fragment, boolean removeLast, bo 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 9907ecccbd..36cec820e4 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.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 void onFragmentDestroy() { } @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 boolean onInterceptTouchEvent(MotionEvent ev) { 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 @@ private void updateClipView(int firstVisibleItem) { 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 dfe8b58673..1d8bddab07 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.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 void onFragmentDestroy() { } @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 void saveSelfArgs(Bundle outState) { public void needFinishActivity() { clearCurrentState(); - presentFragment(new MessagesActivity(null), true); + presentFragment(new DialogsActivity(null), true); NotificationCenter.getInstance().postNotificationName(NotificationCenter.mainUserInfoChanged); } @@ -724,11 +723,9 @@ private void updatePhoneField() { 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 fb10c8d0e9..b52d4b1ad0 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.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 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 void onFragmentDestroy() { } @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 void onClick(DialogInterface dialogInterface, int i) { 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 void onTextChanged(EditText editText) { 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 void onClick(View view) { 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 boolean onTouch(View v, MotionEvent event) { 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 boolean onTouch(View v, MotionEvent event) { 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 boolean onItemLongClick(AdapterView parent, View view, int i, long id) 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 boolean onTouch(View v, MotionEvent event) { }); 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 void didReceivedNotification(int id, Object... args) { } 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 @@ private void switchToCurrentSelectedMode() { } 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 @@ private void onItemClick(int index, View view, MessageObject message, int a) { 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 a2ad121439..84ae277c67 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.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 boolean onFragmentCreate() { otherSectionRow = rowCount++; badgeNumberRow = rowCount++; androidAutoAlertRow = -1; - pebbleAlertRow = rowCount++; repeatRow = rowCount++; resetSectionRow2 = rowCount++; resetSectionRow = rowCount++; @@ -161,7 +158,7 @@ public void onFragmentDestroy() { } @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 void run() { 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 void onClick(DialogInterface dialog, int which) { 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 View getView(int i, View view, ViewGroup viewGroup) { 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 View getView(int i, View view, ViewGroup viewGroup) { 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 int getItemViewType(int i) { 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 677837b976..c48cc65aa2 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.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 void onFragmentDestroy() { } @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 74b2b80f61..303bc9f857 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.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.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 interface PhotoAlbumPickerActivityDelegate { 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 void onFragmentDestroy() { @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 boolean onTouch(View v, MotionEvent event) { 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 void onClick(View view) { 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 @@ private void openPhotoPicker(MediaController.AlbumEntry albumEntry, int type) { 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 fd947b2531..db5fba6ec4 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.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 boolean onFragmentCreate() { return false; } } - int size = 0; + int size; if (AndroidUtilities.isTablet()) { size = AndroidUtilities.dp(520); } else { @@ -432,7 +431,7 @@ public void onFragmentDestroy() { } @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 a9f420e8ce..4c0f327a46 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.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 interface PhotoPickerActivityDelegate { 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 void onFragmentDestroy() { @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 void onScroll(AbsListView absListView, int firstVisibleItem, int visibleI 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 void setPhotoChecked(int index) { break; } } - photoPickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true); + pickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true); delegate.selectedPhotosChanged(); } @@ -935,7 +935,7 @@ private void fixLayoutInternal() { 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 void onClick(View v) { } ((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 2816c6257c..bffc3f51ad 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.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 FrameLayoutDrawer(Context context) { @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 void onClick(View v) { 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 void onClick(View view) { } }); - editorDoneLayout = new PhotoPickerBottomLayout(parentActivity); + editorDoneLayout = new PickerBottomLayout(parentActivity); editorDoneLayout.setBackgroundColor(0x7f000000); editorDoneLayout.updateSelectedCount(0, false); editorDoneLayout.setVisibility(View.GONE); @@ -1310,7 +1308,7 @@ public void onTextChanged(CharSequence text) { @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 @@ private void switchToEditMode(final int mode) { 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 void onAnimationEnd(Object animation) { 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 void onAnimationEnd(Object animation) { 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 @@ private void setCurrentCaption(final CharSequence caption) { 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 void closePhoto(boolean animated, boolean fromEditMode) { if (animated) { animationInProgress = 1; - int visibility = animatingImageView.getVisibility(); animatingImageView.setVisibility(View.VISIBLE); containerView.invalidate(); @@ -3739,7 +3729,6 @@ private void onDraw(Canvas canvas) { } 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 f5d4a88285..0404394b76 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 @@ protected void onAnimationEnd() { @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 boolean onPreDraw() { 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 boolean onPreDraw() { 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 6b64493659..78159d5bca 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.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 void onFragmentDestroy() { } @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 07f4159312..ecc42b8684 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.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.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 void onFragmentDestroy() { } @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 void onClick(DialogInterface dialogInterface, int i) { 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 void onClick(DialogInterface dialogInterface, int i) { 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 void onClick(View v) { 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 @@ private void needLayout() { 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 @@ private void needLayout() { 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 @@ private void needLayout() { 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 @@ private void updateRowsIds() { 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 @@ protected void onDialogDismiss() { } @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 103ac0c181..401dbfe86b 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.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 void onFragmentDestroy() { } @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 a7185bc3dc..7e89a34588 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.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 void onFragmentDestroy() { } @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 void onItemClick(int id) { 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 View getView(int i, View view, ViewGroup viewGroup) { } 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 9c0be40e46..119f3dcd6f 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.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 boolean needAddActionBar() { } @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 @@ private void needLayout() { 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 @@ private void needLayout() { 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 @@ private void needLayout() { 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 0fd9958b11..897b521cbc 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.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 void onFragmentDestroy() { } @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 079bf69260..d6d39f973e 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.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 void onFragmentDestroy() { } @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 37fa05bf43..f5f02e4fd1 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.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 void onFragmentDestroy() { } @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 void onItemClick(int id) { 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 @@ private void fixVideoSize() { 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 1689a0e627..060dbf8392 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.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 void onFragmentDestroy() { } @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 0000000000..bfaa5cfbab --- /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 zcmaJ^c{o&iA3rn(gDgds$}v(AGsZF)+c4G`lr@@cGnkmg7{;2(mKH*!vZRO>p(0AM zcze%t&iQ?RzvuJ$eAnkW&pGYnU@ZodhXDW}W@}?{ zn76VwA0a63{mjJoC2x^qT6!>@X#q@@FM|Y_5ovxT(3avGNIFdNB}RolCm8|27C70( zgXw{{$N1AI2;WT%B9cPqu>ruyG?MP?A53C`exyJ$)fhfg-v|fEL}R$SE?yH)$B}}_ zHqi`{bF_nte{`_F0TFI$0vbhPcmfm>(-(}SgiymUk;d>pbum19^B4&S|Aa7ujp6?Z z$^-8N;%E#KsEg3n@Yh74Kr|YG($PhuQR<+UCQ1vb$-B`SC>@M08l$BL{&m55-WbFH z%wY?wzkKm_#_%8}la4_mSu7TUrH!C50+A>K1A|QsEiDZmLL)4S%JhxYpoS^`RInh0 z`7_9LCYeSBHx+&TXyHs_I4{!wq(GtnElUmit4zFtAtQb1NEAYIGo_zEJpTVfDU`p_ zVa&s%f8zb0!eK5^bQ1C~DU24*@aHuyKzY*@9fM<#e3>+c3yl`?vx-hZG$t)9h(-r- z&S-GIJDEzPvBFgU#N+W8TWT27m+DWlwJ?VB6cA)G5u=AT(?sF4&9!vRbx|lwU44|f zl{s1)hqKhuv(iFq{^VNF{KF|ED)T3o_zxHNOYY_X`YdVg_=zmCQ1ms}(-802PS|EtkIk9gCwY5qO7yv^T(PonasoxvOH{;vKU01)9- z&&(zA!z3Ywp4}~NIxw9A;lGv%Lexs6T8Sw(3T;6W`vnvW$evLgm+^Dgi@O>zZ*K|g zDtlJlJyiYu+OD$Xtz)7dV_OQY%Os^^GjlL@EG*11E*B|7B(<2oYBVUm@>m z-y@vhc5psse90hjP@K=dU+ep>w6?m7BQY;^|8f+pH`OS`DAg!kG_R*q(oSzonyn<8 zl%JlTlAlmMvT;#;eP5EFj2)b*w5ZI2*P`kfCR>79ZMa6nU4l=W1Tyg?gjIxct@40H z1@2fjiXF{W-T~Hvc^OFMnNX#r(@sqTKVb9f4C8q(j*%q$t8DVow)A6Z`Okkmv2Drk z=pA%^7@jQzhIL}8D)W%Ceg&h!E`|4Q_m^F%i9(=dHau7PJh%fc7+DpglBYO=Rv$&5 z2D0cMx;Rkomtzx-t7f}vlRqq+Bm1Fkff~*h&S++$(khk`o&M3|0RNaVJ6dwtk*Gp6 zReN+7$@m!N2}pAqI5Rk^hTUpiM@+Avfhv1>lC8!exZD#T8O;LJxvw*VA5>R528L8! zjPoPa1F*V#c1)cfACJik;e+$HOY``Pb|B*4U7j{#3%<9;-Nyq9E8hrQca^q{9o*s$ z4w85lu<6LlVA+IRuo7bwD_q9b08scwo0wDyf`7grtc0@72;`SXLb zB74dNuyL+Atq0|9=kFHRR|TTmf0VS^7!*PT7q{uFuwx4=IJU~)X75#g#Y;88IcXg` zON+AN3Q_s`vgU$1h3HQtT*^t>l5ABl30f%&%Oz$ z^2)Q{#HtTeSq@JRZR z!Rn84KAEb`i;j;4=Sz(vDNgUaF^y|-?Wp2p z+GIQuDy$y=U0kUyPAo~Bin_MEJ#j|qDnnz-V3*_aH&I!-8`8;8oL_g*dvtlM?PQ;s z&_Y1 zHRS&sPdU|Tw)4rM!3zSgJ?2J_#m)C8HI>9PdmBhA<}9(iP8tRz;s+AVJ4Mg@c9bh$ z3z@z2z1lPs3iWXqI`R0MXp*L-br3A~xhQ*Om6eOD^A(RkiCdOs#bvTak5(Ce1n1}6 z`Vmn&yZB1_1bkM?k`=FrlMS!ZaxUW5^Hqeq!j_g!N%Y;90#;+J4|#}2u}q=sNc_R~ z9Y+a`qLX3P;V`hJAA3*)H?A)5x?3)mqX>!e_PV6MWF28PJC$1?Zt|I-02zoDZkMXx zCi)Bp(%O{M@y1<{-{wy;O|sRV-l`ecco8RD7XA5)AXpbAkp6oDESC`NM`$^nIG4Wj z5cEVfUi*)17|>-(S-4bjH%i}p@k^03xM=G?Z?+(Uq+3PwOP z&A&u_i<2&bVts|2{90}QIfbdkCyVmfcPfjb&4|4=17z#y^LQ8(S9JWM10T0+gx=LtGx<+{AM}f~(Bkp>tNaKYbnW2Dv($3c(9&aV6320h=6e=r+mA4GlycPhR{D(_-W@A%{w-+2qJaOVD;${g3gUX-rF`->F<2jOFLN4Iz|;@xBss?Iq)pTv z=V3-X3<~*Pn9ZSXoH!YGr;>RzVPWIx^dXkHLhOw%#pqyjrS=!0d_gaRWu~~}U6pT3 z(>T43)gmCHROxYGQEo%xnI<*4;;!=3x3$=X>y35WH{KZDvAp8Qw-EY7rbsOF>5P1* zoA;beft%`cfb>BNoA9XShuo`Y___rtO6rHKqz=S&`(&W)_%>`pLu^Eh$R+;z2Hj61 zE!Qx3`8(#o%ASH9jcrtxH`)piu1y^#$041rn*-0Pb=z~Bey4Zli)L_Su9{9j29po= zC&-?06~d;+MF}31Nk~ccHco8r-EdiCp4D&=tvtNczqOcgblBzIjrcur43!-GHOXR# zlZo8gSvT*E=DsDv)SaI)d$%19-62{xQ-3U`>Y17rd$htb3{KxIYH|&q40w`4hUKbn zOJL6~b!!K?DX}jMxxXGPf$`~_;rX(X=GRv{@l7=SwnUTC+?_zWjVrVc{#18&ZVr*n z`+{{2wV2FR&Mjs54@W}5C&+c(-GTirRKcB{KU9kj#EJ+CK9(tP#P+&RE}b>Q^H>`*x`=ey$BR47=^tPl5P zs<}>R?fRV3FVUmiQ|*^k0o=q~uUD{u`wCH4jFYy8X#HW|RMT#f`jB$&!~0rBsz{MX zx#MW!<$uA}4c3=VZuRym-ph_R7hAG&Z#}-@bsD+9_$?|uL^yAbZmMmpFqtlsnr|R= zcXz;5N~cPrx6exa3ksi8ck34)n})%iP}es3^Zfe50XwjXX1Ar+9xr(t9&^-Nk`rdn zZA&G1f}J|^*ma#^1mc2t@%&8@50%i)6xYjrGD8+na82m2ekw>8Etrhy)BrqVBOQi5 zV+v1+(nP}!0!iLV;&%2&w=A#ZI;<&`L9mrdih|G5&y!T)lM{FL3bV2G$;Yym_P5iT znhTCND2jV0l;_H-ZdvYm^OECC=OYw>=U&>WVCYed=YvliiI zlUcWnrCw&=I~Dit#=KqMO(`pthH=c@2C1$Rv!^SV)vZqu06&4NXZJXiuSQj`mv38W6PZ+SzvJ-7&Fu$ImZ|uAc4x&w zP>Qj6aYHM(YY$u|F+?%$_xi->@68wjbgV+!-Y&0JIbQ71H#LJ6N(G<5%lczdz{z7& z^@R5|)sL!fC4JB@_*mZXqT05*WqjA-9`1u981xwT;UR@I)oNeQN0AsVc2$ICR>7Wp z&)7Zmu&;$OfqJg*JR_oiDwf}XZ&_Yzthq_B_q*34jZu4@w+kZ5V|~raoV=*Q$>cM` zJ9>LULsn52(!RY&Q^FfL?oM9YI>T(ze%wyToLPV#4)0|Y z7KpP6Gq-gQ^KneT%&wJZ$!CxqyOg8eHf zdoxR@9w871RhChdc9)Zvha!!EIqHu%dIRYJk=L}GxttZYa~h)js03?a}{R$fg_?H7lFf;1H&9Te(M#E_)@gG7Ea zpm9O&fnEVbFM>bx7bC`vaG8jLQ6v3V3Vs29)A|SfRVHe|WJ#C+S$P?`Un%_tnwkA? zsGr~8=pdps?%(nLSK=Vs&;XpQH7gy;Yf7_x7?w9>={>0z5*nivV{iE%#QSb|(dPd^{y@GLA zgFu2G^v{&lz5Y2CwSVOM%NG03vFQAxtt>Sd*w2m$5-B)LDCim#^NK~iNl`F8S*YZ}cKc7%G=*D-kb*2>Kk=G66 z+%hGSDVc@!TPdnFcGmI>bU#?XeU8NiTcJ-rs%4 zwKUfq-T^a&%h+t#2VB!w z^R9GdG}GDW{-v)S3b#LnW*^wlOib;#JVv-qp1r@`lw3Mnv-_-OdUkG;9TS>`t4xjP z;?V<0ug*F|mE|DA998qo(`ImpmztX4)x*R+!ZO_n$(BU{W36kqRHIxlCwXT#+j{CO zZ(veI+s6>+y;kBs4A$AtZ+BRLn>%kFTbvcl_Wj1$uIZ3i^C&$rqs<_`fJ%51F~hQc z#)9XjZqT=5F}&vMPub8-SKA^AmsbpX2oJH8A=|a*(qx_Kwx3Gc_n@&3ToGLg`j7jQ z+=ElGlyuk03$M2baNX`s?;*y%sk?DL_L^hKz|vi5V)x2wPoOiM@Vd=N?H`sRbTumU zKKc@+w2%#yh{M4+GiL<@a#=7{m#ad&{T1Sj-5nZ5@ONye*kXS#q5$r25T072ETvR4 z=(!VS4IaMG)ih-NKy;vA=qc2L#*|w#<;3x+lA*6B9#t8CG;TNx1LYT5pX3SLeJgs{ z&VtxB9SHoMckx%DCBLvuZvhg#jI!GQ*+sOUXJ6DH@F9>M`-x6 zL2Ya@;@xe`SZY#@cny?pG!pV7!bdp24mVt3{+0U%_ge6Hq^o@Y))JDM~FFlc?e+QWr=fE%{ z4!KkGwiC%u!&CZ&pST=&Iu@UJ9~1h_ikF7fO|54k9CDuHMts7ebJLn!V(vi8jg>s@ z-37eR!lQV=CbE^#fM%&yoLmlAlgN5gWsVX0>Z2$|tLVl?t44=@usIFPL~CYM5-JlC z+P{$3!B^wf>^@v#+6z`mvf7&Ma5(+(yXOujW_8=Nf^sftl*46lDASbHLwXHA!Z%xdLq>44 zanFdXE1DDt5@;KvONvz3euQ|m*|cl*CIXwRB6oHka(K_guznw4R9-UTZ>zl(fEm=FYj|=R8l-KM`cK{>b{c69rr#8?PQ* z5&7D-u>jv$hHN+|sKnK5uwypQ)N4m3bUq&L_ADCoDNP-JDZj%6*5jY*fJ?RrG< zE21B4>6uHJ5-oV#LiR#kKdmq~!#drzT?v#0Nv3KyA z{r*LNS_%EI6abfg5HEqj2%p>rfM{NFnHrig;@T! z@00=Gc7|a^(1mB`=(fY#x5CBRJC42QWj>ooI7cCK+t&j~-C>);?w)i@xplRbhD**b zbAWL=SISI|u9R*7c!YIYT4UOqUAQjUKp?p}K3Y8zUu3yd+33=E-N!p@9<>LU#-QS9 z$GGPxMFH;h{k#>^aMGPmr0k=sYd?ZK8&xc-X1;&<%$NzE!ORaG!`$}QCb*Y;UUibI zp0vY%5o5-ukv2fsMs@S~cdJ}6&m8{gN^WX_!S?hR8- z&@~mMtZS4VKW`(;b4S;|J@miW8uKarE~hK}I2}GM=k+43$j?J&%QctO9+n?^=TfgKY7r%~q)?lHhot`L;z4G!dL%ehk!HISgFC zJMDz~cCq9BM+J>Z`jy<%49*9*LLo8>-!W)a96+Hy)+z$;Uoq=RPC8T%$CJGnMA=JdS>KY5MBU(D?PDDgNx^mTvaL+ys= zu&itFyM=c?nX>i3%i{o5>-QyKP#Ab=VDptr*`4yDDfSZo?%bLK{TC__=csWhZvs9@ zZHK-&Y$AB1z7|H;@n9iC@{mt&ykT(Q>X_eI)_a1Hkq@KpO~{`wm@ENJ_cix~-3?eW zahxe7OZB{7>|yt@gSb9PT>oyWRn=B|LL+omn$-~qH9&c``xFD!TqJcmnr zAzHI8Fdxixo~lnOftQ6^9TkON$Xls+SmbuXDw}6Xt@F4P(^`HR9bT9>l8$V9%iA|9nK~#=xaEft4vf{Hu@hBa%y% zV$c^4Ex9J38i(qP(XM{17~xz>`m~|JTrl$}%^eaavW?~F-sPg*O*TK`oA{KG{4DV+ z!|z%P<~&93BMIOTzn4>DDb=f1DNDSpKAN@(;9^Cj(7&!2dq^1^l~qegQ2oc>W6tQMNFl6RC!8ZW)A zXbj-DTdnjT5O+1h@)cU0VuSFrHC5X@(iuzg~4a1Zl?T zPHS(Vg7GnLtHH2TSwOnZY3}mjt1qV_ykd%mI8do3aLW}gjR!`)bDBJv(XX?gPy~k4 zD0H_Az(SzX`7f3D*x)&cX2oojtB>H8uX?1ZrbMJS87|arT>kAkW_Fp^qVe(3#dp0$ z{NcHFEcOcV94C!=1GgLP)j*4s0>-kJ0=k4dp=gUqVUN`%4{g26^ zI}__E4xG|}q5L&}ak>81@Z;O!fKRMGxyYDr80DK_MVXp7l-p%kHBRiwwySUVBlCje z!b2&tDY*bm1}Ac-ugmNP=}^l^9mGdrykqJVZH(GKYPqxSRaQsglQe~+Wz}=O ziGW#pZ*BQAk`A(TWMx=sTFgqnJ2iLKi}^g>4JlnKu=+SA?4eQNLhE)(qmk6%ZS|4L9M}od|5q(pcRaw2}}3)K9aH6E}|exCn#y7?LNP#R|o~ z2-ItzX_DnX$&)?F7Ni0hs@}PtNZ0d@0vQ3U_OT9n2cnUPHf3>P30e#?OFgxID12JxdI*aj`p zp-G36r&T5* z4^Adv+N9L~?j^VSuJz8hMuuHPKNSvQ zo?z^?X!KsxadR@7=Mc>YfETx;&|~>+9kD#Yw~ffHhluhU`6qnEwZ#>rA>;jp@^MTL zg(C&sJRDl18_F`$&GHzl+v0gD^x0hLOglirXr=+9{8d99KNmLm5!+2JlH?Y{$WMs2YB&kqYE^dpuGd>>~T~pN7G@FSd~x$7fR{wHV%dm zl#YOzfGuhA|i^{{xGjstFN3qH_^9rX??aw=`m$?I5bJ}Z7ML~m!4IMwV z*_tmG=m_TLEzsaLuRJ|47Cv=LGb#lh!*;__K)5(w04>2ZX}o{!zRUZHOsF@cmSi69 zrK-0knZ@2z4dH6F-G&Wx&v-M(?$MP|KcHb^+E+6HNo$&t|0jU9+W=bNC%UZLF*)eR 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 zcmV;v1ws0WP)1mLYmEXv%7OVzn8p8ep&aL+1adtKKRJYo1K~W zz4v?H@0jq-uXMAO+yq{J5r~y9!{P!jf6EWN|X}aS$&d4VF$ig*; zH}agZ7Jpl~ExMS?H!#UgDe(Nqfj4VKpjW@3jr3($#2u1N&WMaUQ@&oDj&$&>u?b`@ z%DXfSJPahmBybh*7&({BkcVZn^^T0X$*MMCI&wD87`HIV>83vh+z)(J?tY`==C$R1 zb2acNF_oljbOvN=?hr_1tG0gAJ&qL|<(9Cq8tZj$OuzS2;O}Y(Tns!(27g4xtf!XP zcSsGBG64d=az|{?@@@bZ0&f9s5CZFf0X0W@@V~pOvQJ>fPSngRMcrd~&p1}&QcYkL za3=6!5KsJ|c1Wtt$hbAYgtThyS+Tm45QG;<*Jf=_z6kUIo%-0uL!bAnGF6divA%@5 z9VA^!y4Uz2uxHW8A9=WcncA@V{!J~_pt(*dPSO0yzdy76QpZvIRdSKr^S{Vvq$S4E+aJggq&Vij=*J$ zSL8T0Qo8O0VzvsuJ@s2pl(Aqw(6ex(A-@i6z9-C1o)vc^Jm{WtLP92B&w~(y3I8b< zq+7`E;p8qLV;n8E0^P*L2T~p}9o>%DW_lmM-t(vyqo@ZCkLsQT{^Cx{8^Q zAo0CYfTO-=K4tbWTkI|(4koVMr&h=#92(^P&x#M6I_Y8rQe-BZ0=}la%5eFO z|G0uT6&zDWTU|!4%8{0F6X_ZBlM_EfG`N?~n7zwAevypsAoWvKy*}WFfZELaNszWfl>nD* z@YB(2^J=DhgVcqd1Ag@6mS-aOK$X_i-0szC+k&Q!`+&ni2&nc5Qx)iWMQFu-cnICI^v*;ch)^(urCg4Co+NVTf`%&IDR zHvn6hzb}?5Ap00N6m;NW5uinlX%N7X*gaQH%I#B z@rWVa1zhwviF?2_gzWet0OXl)A8^I8JAa0V*@_APdG_mvz@-Z9N!}mh5R$Pjz>t4p zHfSa72k-$Rvev>V$X~$Ykq_hx(X7|n3V=L|8~|E;4)JqXg-IImH z(;3t;2e|Kb1@2nT)>2Di5)&!`XviD(W)&QF?r2wl&om8HAmFN*Oz~l^)x+VS3(@=~ zWvLs#vIxGj6sKVX$R$N@^(O0YN(CfTWsL& z%}^5!A|Gg0;6Rhewt%>JsOvO}a5{q_Ulb*>dGs`-Ok_@gmfi=D3zB#|u7Z8a?mPy! z&PiQpyOi(wXe(~yOA0WJz6MO5IV^d(4{+n(0SZ{dL>{OGnDWL{K;(Js87pNKZ0Hmo zH+&ZGv7EAFxd*mMa!P=H*+RKBQ%PZqFZf*8YN{~#Rgj;sRu?)af={XaWWO$2FmZiU zQ`}{@dq7Tg+UACx)RfxQ-v=NhZiIL#dhy`Pz&yyGsES7xzLB+?@=Kc_C@|R#U=hR* zy^L?8XtiO$eI<*^F?^4Wm{~r}UpSql_??`uGgd5W*^diie6#R7aVQ`ZP~!s51Q-A@ WDgnbN@!%2w0000XChpGY=NxiA(B--Ry_f?gTHkXPm6Tleos}qX~HTuAI zU=Pp_NEYw?2N(fPvg3vlpn@L(Zgfa{A2T9<*V}}sz%K&Zu6h!pFfF>pb8gu^DT<;h z1*Mt%HC@wXEunR0^=v>-={o*3 zvT$-Sxk-y_J3;E!l1rn&D?r3a0`~&1bLR%0_8DKB?@N!*6RE{^)J1h;DwcZ4$Qr!U z&jT+2KRH3*KH#@_Uka=b40sjqm3nPTN=P{`x5{))jZJL?UbRc$ zCAJ|^vx(xz--F$2_1;-QU>X787&mnfGh<5xb^zV%I3oq553EL+T1HDp%UMLXQ`{5{ z-R)Kg9LXQJJgyPn8sG1Y&T-%qUr@8nTNkjeS^{?i8}boH=}=BJBS{kk!GOPg#!Wp@ zPTq0^9xH6qUia6~fZD7~(--nxgchc_seLOE2m)K#u_mvP$D5um%kJ;F)7>i(xTA2v zB~H2}ccR$@;C~ZbSlwEPj3&ukZ-IbEJa2o|%ZOl6a+qY1^a=PYq6P?(K@uWUmMboV zZowt|V(7-roQ&gU8ra6E&R*oXL=KQ8avWk)ZTgXQ28oWa93~&(+J0MQqf7jgJMA$u zA(6}P4XH(%wY<^-o=%E9WfB}bxb|F5JJz)@$DLkhMxd2T*kVvy#(G9(DtvLh7R_|)blV`1EGK6v0i8Q`{g*lq1~G(XkHCaLjJv^Svq>{m z#dm(TOh8{IPt1%!gtb2?1BKSH*0V5#%91B^l>zz5CzdTUlMQjFvz0coLbyV`y52H@ zb>u9{kU^8H8j;9R(qUZ#Akf8~{!xj*ME(Hf-4xJ2JK?~1kO~U^P2AMEN*ef~;5b?1 zrgS15YIX!tm(;#oWG@PztwccM7z(MS)Ll&tpN1jmDZQVY`m~yQ;2o}`)}K)`fo2g% zTuy8Ui7qZmep3wr>LmHjv7ES)*xwA{bL~h~+sjQ2TB(WO=0aFsd?DV~Xae#1_(86J zO1sx5tq`Eje7xWoN$ntQ0X9nb=xp@(&xce8^;%h{P% z6_lzXVh%ZWaV&Zn6eIZV|9@TMLpmN^NBSGqojY)O-RC!XIiFrt9=@a_;~FReL8()3 zPF%14XJ+NQ5G!uo96bt zk=XpXZp{wcw;j80>eVoY7ckd9;QN>U=p3JU*{%)Ar_MdQTbdu&!G7o9H?6s|Tiey= zZ!Z4ew5L*C?$gtY|N6Mtk8qdy-l*O3qcMDWZRZrej_Ge^ZThWIxL^6+K1Xf#BidzK zAN>>g*wcNLujBfgS)MVEgr@H}qN-Qe>5ZHDBjw}SzrK5Z9c0K~y;$L1SbKd{f3>B; vz4AM&B~2bYZ>YG>xc}h&h3lRzzQvxOwR6?2$h(JufzROS>gTe~DWM4fO?JkE 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 zcmai32UHW?woXC<1Pve^K}cv)LWj_Mk>15n6haaZO+tVuASj_IC?HY{B8rMclqNNZ zw1^zsY&s*BSx7}sGg00029wXt+# zwah;cCp+uyHcH@NHKG(NG{rq6kP?9j!voB4Apv-}EfEuhcf(_FQK6l9LjZtHD%b-} zK|4C=V?&54m_IZskwh|!8vrmgi6mpNXYmwx06r*~WF)oN&>{s7#u-VS&~{XFBwOH5 z2isf-!@FN_^1xm=i`BzPnHa+jBlTGTL_7rpk0cUE;rfwAQvbl!XZ8O~t4hKDK|(oe zB=t|F(2g!}i;yrpTw6s`8LOtQ4o9I>)U~uxD0L)ULrq;nRgHC{l-0HLwNd&SI`Ds8 zQY>jWs{9kTjIZQPYLsnH+QTt=k zUxbd1|2HX-_;2cPiW~kv`u?xL;T}Czx@i0@uPRF!)jxs#Z-M@6ij_Toy8ljF z*5KcXk0-IRJ&cvs{B8kD0Dz#6t)-bqqevZkd&NwWuOS!r4}Pb3=- zx4w9{11#?EYB4uS=Yw;LzX$_%>mfU4)EheD6p=@B>DlH`UeUusdNF|()q>yzWL!wFss zfnKNO;%?gk_T$p#J!l(VDvyZ$Qzu)=`MYymBNXg#EJqtthPr)uJN38+DDnzhPpU~C z{qi(+lSXf;a2yjyva8IM2W@83IlIGUsoPBYJ5HK&Z|Wl3g_Zdh&!I0)T%;%AK$V$K z)y!6kc3z+?70Zm;)eb~8bjEl{E~#`sY(+g&IxYISu0r*2&x)u$3&ns5Q!s3^uAcun zJoIUG-cM?$*(z#JZXMiTmHLpmYXS9F=sKL0Cf&?$B(t7Xx)TB&sd+Hjro>gFF?c_X zk7?{ryN!2Xq@NvJ6S(u)CP!^odVyozgQwbI37<9322|0k-h)akeqdjnZ?PGA!~>bz z4V^Tn@hFhFJwSz5fR5!a-%&>!UT69nLyC0yw6yZ}bt_f74`T6M^1#d!dy0W_D@RU7 ztxv!S31Z_iPR-;`gDLpiUJ?pGKDSGak(S;c)_pgFDp%5l8G0$8jh`~1C`e9fS~kEI zo_wkJ(DdPt?C|-@gbG+=bP|2QZj>1Ye8 z5n9fjoKZ#hYclU4v7vgy)Q*bpxeK91}sUMdr zDtb>M0*7VZNGF~%_pRt(=3yJ=8t4Q8CGPw6Z_Dx?GpH0~>W`pWDD%z|!VELpM=6~l z{;`@}5ui!*>b#*N{s01+KV|Y1y^;~C@gW0u)Wa1Q5e`uv;;Q*|6L3@hcI0v7*+NmC z`xFzer8w6+pMUah)1~DN`F;gGQL8ewnXD8o2=C8=Hc+^u=iuDs7< zTj+DAqgDX%v2)j!qLM)+5(T~A1x%1mg@u>w>M~=Ym%`1CGCDy*zAg48!ip;qp&-cwphU{87Ajo zt&?XMprqfXfW((K)1E9Ayg$SMVG7Du+8wxJCS`T=Rt%I^f%u;0x4|H|54uF;-b7-2 z{2(76{K1cE=*2d*<*r+6i*gXMf=}F*3jckM_Qh2rnYKNUr++v|lDGaBT~z5)#;)M^ zED)urp#)4#^5ZiTJ7*I)((MTd7ChEAs(MG)wz}abk(PSRZ~3FHbK++i<^=y}+tg^J z2}bPBQ`NLe=ejJzvv(bb#|UOo*VMnA@C6UG^THK8H0%*q1x@#QeFDDoR2ifSF!bW* zdlmxO%CSl=eX=0tTv1@FDwLjC*uH$@(e$p!);onZ39K%@h+Hr5%*Lo+7UY}tE`_hX zt4feFE1^ZpK}QN`Xp~o+zbK&d%p6dmT_y#!ao^Cvhz$rxNWNXf4(5z&GCTI2J}kP0 zo)OQR(&Z!{?|LMj;n@Hkfvd$@fLqee?F+Y}l2?k0w(e$?Gs5BkIrN=^b!cV1mF%mS zaDs~TgQst=)t{SuPigvoo}}bS`@-M{)SXZAS*jv$U!YdNs+5sk(>hZ`ZzQ3*6B+AS zd?}}RXQ}X_!uR+0<1;gN-p!TfH>c%KnV(6PRV8wDZ_=Boxi=Ym_j25MYos8g==4X- zHH6o%80Ggp^2na2mXraZNl?l-?0RqE%^p|Eb{cQX2ZZ4433M&E74{{Rmd2yf?v|yH zHhj5guB6z`4luJ+Q|8eB0D;O~bh}ZbB+Tq+Nh!|YqnaaiGC@v(>%5FO;U61%I|i0f zy(hHYK!Bq@`quLMKU-1ukAL0h4tYJ^6MiibN-g{SLMWZT`@S_|oyTu+Ws zEPxshL(P?RjN_hF^gg;K8lw)t2y^VHUw2Z|3r|Pk58Qg4}D|@ z&Cf0!07o@MmBMwGy{DId7mt`yjl^TGo*d#DSaUTP;)1W+kVppg+#l z$h^M!i(Z5+31kDFU!AmK;FQRjMV^3;x@MuF@&GoVV&sZO$}KS7Q1*q^-fCl#MG1}# z*cH8^k&de$oTl??4DNm%zST8i3b^+jy%wb8^7Y|*wV>&%@2>f`YMPR1!q+EKA z`N;ybd10y`YwmJ~-MgeR=6Jq05O;#y1mCa|(YbcWPm zl*olFv$yLcxOp%cFfe*X54d#wnxTZ`ig?rX>4`a(E0MTk##hTsm7F^Q@sAn`DXP~> zdHvi`YKgXLwUdb(j3;t>57*2~^oI!qqE}1bemh-42vG0zlro>!Q~d%IGy8QO0V#Mz zVl-uy{;oxHOV{V=n_HahI^U#lty8Bs&)>H!=z+E82?j_Tx!`A{nb%?(H=PI8g@rvC z2NsN8Vuj5oFg;fw8@iUuc?-c)`z&?|V}9S{jO=uQy?6Cgxjan}IyEgX!6yj3VJ=?x zDBZD4cCc6?w(y@i+saVbo>dz0E)Wqnxx_sDHd2Jm8D8Q29t7X(_a zFRUYI!aP2PU()3Z_?1}O(%1BZgpkZ2*M`gZS~@mg^g}{6fF%9Ve6qoP^0(ZJFbfs2 z<#;|*v%u-RA7<=|qvFajdp5LwWid?^=BeW#d6)8Ul&LzJ{@PSQC&Rr-N1;{htSmK; z`K0d+@6WxSu&Wg?jV`00w?jv*H!EJBjjr8&rhI*xEIph(T6{!^`=ohoyv5i>fji@+ zdLgGHo~R05S9mETXW8DZ@Q9}#YT1~Jx(vFfbEbLDkqzo><@L^Ycr#!Q-W{utL3Ro4*Pvafs$%tG{X`AwU>$h zWi9z>EiM(=cYe&a?;othiHckJ9d;+1$-O|*iuf-DB`@BY zKM0Hz1;01;K6i0@Fe7N+Igv=NV)!}iiZVS-pFgqgVO{}G3^xg6MVz@)q`i?9D`>j{ z;nTBypY`!UWP%5|^pnpJ`*!04Xp<)Ro1wtRmsn|lPaI@t&i2D5k*w6e_s+NYvA>u4 zmrLjTmEcWiG0V=G#KVs2k0w&L8!y4}(r9Dh81c{K`%rtn&E!e%(3}dGxn)Dg=+j>H zpBFO`EU^CGD`>L;mTvbFC*(R)DRY&Ax)ww1b1NaQhKf3R*@qlKBJg^`pz15R>XjB5 zLO8736}k~Fl4bh6mG6XSeQ&mDz~><-)6<{3ot!Yodn3Wm`|*VcyQ50lAOeZC8pZZK zRR0C(Zr|5;1|*yc)VXJMaBeuZyaMKQt+;4lVq}PGUV)Hs@cqQGAr8Y5KfVOVM8Frz z$MOkXEi!Em<2Po^=3POZ<{<~v`+$emfnpQ*ab6}sRsL+@euc{>QV=w`t!pq3DG`rnXVOsO?mkdX)^(2>*=wNjDj&s#Y zi!7^Tndu}Qsp1D#I0TLIs)yH2_)g8h}K zwd$bOizVs@RXYtX6S;%x`#!55M?_7f-UOvw=`3*cPOw*wylYFnCiC%vHMQJu+kSTj z1MBuSE-xA85|<_<)Tq+ijhL=0cGvDt)`o-CWNulmOrw0%Q*OpKR`mLzokINyoO$91 zLYDoEn1*BH?JrD%jbFTf`U&w9mwIqVE)x|K(JJ(-)5Bc82ttAk!$7f5{pR`nK_g8t z(*byI1HvkI4)*UY9vESokzzYu=_T8`*bY77hd_ySuY?1?xfg&rsUD-xC|+~-SET)% zR55uM70B>#Sh78h{ROl3!B-tIoXq-3>`N-4Yx0U{jcmQ}vC;IP*eB`ytC)2ag0O059?QCNxkqe&LgQr$T2=S*@43s<(|pXh%B6mE{XQopOEg z3d~5qE!zs<$bO*Nzn2HuZ>ARXF3^O$s|0ng?)RNRq2>f0DiOt#%WMgu%kL(_WFyCK zor9KZ2{AbYGB|8+5G4TR@3*}^)u|1SDdyF-sOo0AHNNNt0jb8cOn-sSvq5WG_6GOf z#9IHjeA$lr+m;%$&cM-_8AMh&cV{C)YTxDVOzuK906}$6Dv`IjiD5&~*TN5du2b5) zD#of~JV9+d&$>}Xr>l8vmJ!_vt*E87`s5vm6W>!$kPKTJuekGzp8(?1kKbP zq(Ji^@3sS1S7Rn0QzaFzmt0Wdu*wb5`z~u5SQjXvXj0H{LuL8Yiu_npy5QJUUiurO z-*@M-O86w}A1+}R&ClZ_Qa}?Gz5#)|o6QO->EIzyp}%2b{F|3*-BP}dP0ECX87G)g zRIE*q$q;&AxmodQKNx_@6|Haf%9-=dJpvSeH&0qh`S$aL!S*mx)@)`0v2J1qH~>5V z2&!R6N(tI*ITVTV>LyY zxj$2oispJdB4eysYw^P@*jJZ!e5r-B@viw0~IQ$5QNCeZXWq2BrF`X zKHGb`iFbI+SbCe^_eE=(=GmPnS7S7gAT&-?5coOxk$#-$ellJN(igY%!K=*A7Rsx`dn=(j>^I_wV;sNlXdJ@i zHq1a^&xot4tm)X>ZPRZOrW*h~uXy74QOHqy4j1yKXHvWauXc}IG!Jd;psnI9D5s=< zR)%CxPg57?nOPN$c-LpT` 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 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 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 0000000000..881a09d0d7 --- /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 0000000000..3b437c2486 --- /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 0000000000..f8dbdd4efe --- /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 0000000000..c5604e3a28 --- /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 0000000000..40a9cf0f5b --- /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 0000000000..6fb0453d70 --- /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 0000000000..942b7063df --- /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 0000000000..9377186e9d --- /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 0000000000..93eb900898 --- /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 0000000000..f311824b83 --- /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 c2c53d1295..55cb84eb48 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 0000000000..b3fe031297 --- /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 0000000000..713cd0bc37 --- /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 0000000000..92447f398b --- /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 0000000000..e34bbba26d --- /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 d1d4b45940..0000000000 --- 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 d1d4b45940..0000000000 --- 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 0000000000..98c7f0bd2d --- /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 0000000000..43c2b9d32d --- /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 8cbb7ef3a7..5562767b26 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 df5390eb62..d171f0ee5b 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 8cc0c49f42..3c328ef1b0 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 8b5e8022f4..d826f248b3 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 f4eec4eebb..f2fc30ddf5 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 49562999db..487122018f 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 4b4e6d2540..d9e826d5be 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 a544d799b0..02883ee2d0 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 903c5d2cd7..782c27627b 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 56449ed431..444570aedc 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 27fd29715d..89ecdcf968 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