From 13beabf741f8e62c5d526ef4efdb2d3ddbf1e201 Mon Sep 17 00:00:00 2001 From: Austin Huang Date: Wed, 1 Jul 2020 13:08:28 -0400 Subject: [PATCH] init --- .gitignore | 16 + .gitlab-ci.yml | 54 + .idea/.name | 1 + .idea/codeStyles | 119 ++ .idea/gradle.xml | 21 + .../inspectionProfiles/profiles_settings.xml | 7 + .idea/jarRepositories.xml | 35 + .idea/misc.xml | 49 + .idea/render.experimental.xml | 6 + .idea/runConfigurations.xml | 12 + .idea/runConfigurations/app.xml | 53 + .idea/vcs.xml | 6 + CHANGELOG | 193 +++ LICENSE | 674 +++++++++ README.md | 5 + app/.gitignore | 1 + app/build.gradle | 50 + app/lint.xml | 29 + app/play_icon.png | Bin 0 -> 145258 bytes app/proguard-rules.pro | 21 + app/src/main/AndroidManifest.xml | 218 +++ app/src/main/ic_launcher-playstore.png | Bin 0 -> 71824 bytes .../java/awais/instagrabber/InstaApp.java | 66 + .../java/awais/instagrabber/MainHelper.java | 864 +++++++++++ .../activities/BaseLanguageActivity.java | 11 + .../activities/CommentsViewer.java | 146 ++ .../activities/DirectMessages.java | 113 ++ .../activities/DirectMessagesUserInbox.java | 101 ++ .../instagrabber/activities/FollowViewer.java | 348 +++++ .../awais/instagrabber/activities/Login.java | 130 ++ .../awais/instagrabber/activities/Main.java | 480 +++++++ .../instagrabber/activities/PostViewer.java | 639 +++++++++ .../activities/ProfileViewer.java | 215 +++ .../instagrabber/activities/StoryViewer.java | 354 +++++ .../adapters/CommentsAdapter.java | 136 ++ .../adapters/DirectMessagesAdapter.java | 116 ++ .../adapters/DiscoverAdapter.java | 87 ++ .../instagrabber/adapters/FeedAdapter.java | 486 +++++++ .../adapters/FeedStoriesAdapter.java | 57 + .../instagrabber/adapters/FollowAdapter.java | 144 ++ .../adapters/HighlightsAdapter.java | 53 + .../adapters/MessageItemsAdapter.java | 354 +++++ .../instagrabber/adapters/PostsAdapter.java | 92 ++ .../adapters/PostsMediaAdapter.java | 68 + .../instagrabber/adapters/SimpleAdapter.java | 75 + .../instagrabber/adapters/StoriesAdapter.java | 84 ++ .../adapters/SuggestionsAdapter.java | 60 + .../viewholder/CommentViewHolder.java | 85 ++ .../viewholder/DirectMessageViewHolder.java | 43 + .../viewholder/DiscoverViewHolder.java | 22 + .../viewholder/FeedItemViewHolder.java | 52 + .../viewholder/FollowsViewHolder.java | 22 + .../viewholder/HighlightViewHolder.java | 21 + .../viewholder/PostMediaViewHolder.java | 20 + .../adapters/viewholder/PostViewHolder.java | 23 + .../directmessages/TextMessageViewHolder.java | 91 ++ .../instagrabber/asyncs/CommentsFetcher.java | 265 ++++ .../instagrabber/asyncs/DiscoverFetcher.java | 194 +++ .../instagrabber/asyncs/DownloadAsync.java | 248 ++++ .../instagrabber/asyncs/FeedFetcher.java | 194 +++ .../asyncs/FeedStoriesFetcher.java | 103 ++ .../instagrabber/asyncs/FollowFetcher.java | 101 ++ .../asyncs/HighlightsFetcher.java | 87 ++ .../instagrabber/asyncs/PostFetcher.java | 146 ++ .../instagrabber/asyncs/PostsFetcher.java | 134 ++ .../instagrabber/asyncs/ProfileFetcher.java | 83 ++ .../asyncs/ProfilePictureFetcher.java | 120 ++ .../asyncs/StoryStatusFetcher.java | 102 ++ .../asyncs/SuggestionsFetcher.java | 98 ++ .../instagrabber/asyncs/UsernameFetcher.java | 54 + .../asyncs/direct_messages/InboxFetcher.java | 100 ++ .../direct_messages/UserInboxFetcher.java | 76 + .../customviews/CircularImageView.java | 105 ++ .../customviews/CommentMentionClickSpan.java | 17 + .../customviews/FixedImageView.java | 25 + .../instagrabber/customviews/MouseDrawer.java | 986 +++++++++++++ .../customviews/RamboTextView.java | 179 +++ .../customviews/RemixDrawerLayout.java | 182 +++ .../helpers/GridAutofitLayoutManager.java | 37 + .../helpers/GridSpacingItemDecoration.java | 31 + .../helpers/RecyclerLazyLoader.java | 67 + .../helpers/SwipeGestureListener.java | 34 + .../helpers/VideoAwareRecyclerScroller.java | 282 ++++ .../masoudss_waveform/SoundParser.java | 252 ++++ .../WaveFormProgressChangeListener.java | 5 + .../masoudss_waveform/WaveGravity.java | 7 + .../masoudss_waveform/WaveformSeekBar.java | 225 +++ .../instagrabber/dialogs/AboutDialog.java | 98 ++ .../dialogs/ProfileSettingsDialog.java | 62 + .../dialogs/QuickAccessDialog.java | 169 +++ .../instagrabber/dialogs/SettingsDialog.java | 213 +++ .../dialogs/TimeSettingsDialog.java | 173 +++ .../directdownload/DirectDownload.java | 153 ++ .../directdownload/MultiDirectDialog.java | 117 ++ .../interfaces/FetchListener.java | 6 + .../instagrabber/interfaces/ItemGetter.java | 11 + .../interfaces/LazyLoadListener.java | 5 + .../interfaces/MentionClickListener.java | 7 + .../interfaces/OnGroupClickListener.java | 5 + .../instagrabber/interfaces/SwipeEvent.java | 5 + .../instagrabber/models/BasePostModel.java | 82 ++ .../instagrabber/models/CommentModel.java | 85 ++ .../models/DiscoverItemModel.java | 29 + .../awais/instagrabber/models/FeedModel.java | 56 + .../instagrabber/models/FeedStoryModel.java | 30 + .../instagrabber/models/FollowModel.java | 64 + .../instagrabber/models/HighlightModel.java | 27 + .../instagrabber/models/IntentModel.java | 21 + .../awais/instagrabber/models/PostModel.java | 50 + .../instagrabber/models/ProfileModel.java | 75 + .../awais/instagrabber/models/StoryModel.java | 69 + .../instagrabber/models/SuggestionModel.java | 51 + .../instagrabber/models/ViewerPostModel.java | 63 + .../direct_messages/DirectItemModel.java | 490 +++++++ .../direct_messages/InboxMediaModel.java | 27 + .../models/direct_messages/InboxModel.java | 63 + .../direct_messages/InboxThreadModel.java | 145 ++ .../models/enums/DirectItemType.java | 19 + .../models/enums/DownloadMethod.java | 9 + .../models/enums/InboxReadState.java | 8 + .../models/enums/IntentModelType.java | 8 + .../models/enums/ItemGetType.java | 9 + .../models/enums/MediaItemType.java | 10 + .../models/enums/ProfilePictureFetchMode.java | 7 + .../models/enums/RavenExpiringMediaType.java | 15 + .../models/enums/RavenMediaViewType.java | 7 + .../models/enums/SuggestionType.java | 6 + .../models/enums/UserInboxDirection.java | 6 + .../instagrabber/utils/ChangelogFetcher.java | 50 + .../awais/instagrabber/utils/Constants.java | 45 + .../awais/instagrabber/utils/DataBox.java | 271 ++++ .../instagrabber/utils/DirectoryChooser.java | 248 ++++ .../instagrabber/utils/ExportImportUtils.java | 328 +++++ .../awais/instagrabber/utils/FlavorTown.java | 98 ++ .../awais/instagrabber/utils/LocaleUtils.java | 70 + .../java/awais/instagrabber/utils/MyApps.java | 138 ++ .../instagrabber/utils/SettingsHelper.java | 115 ++ .../instagrabber/utils/UpdateChecker.java | 75 + .../awais/instagrabber/utils/UrlEncoder.java | 74 + .../java/awais/instagrabber/utils/Utils.java | 1270 +++++++++++++++++ .../java/awaisomereport/CrashReporter.java | 197 +++ .../awaisomereport/ErrorReporterActivity.java | 101 ++ .../java/awaisomereport/LogCollector.java | 138 ++ .../expandableadapter/ExpandableGroup.java | 40 + .../expandableadapter/ExpandableList.java | 51 + .../ExpandableListPosition.java | 41 + .../expandableadapter/GroupViewHolder.java | 39 + .../main/res/drawable-hdpi/ic_download.png~ | Bin 0 -> 1070 bytes app/src/main/res/drawable-hdpi/nav_up.png | Bin 0 -> 302 bytes .../main/res/drawable-mdpi/ic_download.png~ | Bin 0 -> 793 bytes app/src/main/res/drawable-mdpi/nav_up.png | Bin 0 -> 204 bytes .../main/res/drawable-night-hdpi/nav_up.png | Bin 0 -> 319 bytes .../main/res/drawable-night-mdpi/nav_up.png | Bin 0 -> 217 bytes .../main/res/drawable-night-xhdpi/nav_up.png | Bin 0 -> 354 bytes .../main/res/drawable-night-xxhdpi/nav_up.png | Bin 0 -> 506 bytes app/src/main/res/drawable-night/collapse.png | Bin 0 -> 3457 bytes app/src/main/res/drawable-night/comments.png | Bin 0 -> 9189 bytes app/src/main/res/drawable-night/expand.png | Bin 0 -> 3510 bytes app/src/main/res/drawable-night/expired.png | Bin 0 -> 5286 bytes app/src/main/res/drawable-night/mute.png | Bin 0 -> 7877 bytes .../main/res/drawable-night/video_views.png | Bin 0 -> 11908 bytes app/src/main/res/drawable-night/vol.png | Bin 0 -> 8473 bytes app/src/main/res/drawable-xhdpi/nav_up.png | Bin 0 -> 341 bytes app/src/main/res/drawable-xxhdpi/nav_up.png | Bin 0 -> 448 bytes app/src/main/res/drawable/check.png | Bin 0 -> 25320 bytes app/src/main/res/drawable/collapse.png | Bin 0 -> 2760 bytes app/src/main/res/drawable/comments.png | Bin 0 -> 6101 bytes app/src/main/res/drawable/downloaded.png | Bin 0 -> 12702 bytes app/src/main/res/drawable/expand.png | Bin 0 -> 2813 bytes app/src/main/res/drawable/expired.png | Bin 0 -> 5491 bytes app/src/main/res/drawable/ic_add.xml | 10 + app/src/main/res/drawable/ic_discover.xml | 9 + app/src/main/res/drawable/ic_download.xml | 10 + app/src/main/res/drawable/ic_feed.xml | 9 + app/src/main/res/drawable/ic_fullscreen.xml | 10 + .../main/res/drawable/ic_fullscreen_exit.xml | 10 + .../main/res/drawable/ic_import_export.xml | 11 + app/src/main/res/drawable/ic_profile.xml | 9 + app/src/main/res/drawable/lock.xml | 12 + app/src/main/res/drawable/mute.png | Bin 0 -> 6263 bytes app/src/main/res/drawable/slider.png | Bin 0 -> 3371 bytes app/src/main/res/drawable/verified.png | Bin 0 -> 6450 bytes app/src/main/res/drawable/video.png | Bin 0 -> 6913 bytes app/src/main/res/drawable/video_views.png | Bin 0 -> 6672 bytes app/src/main/res/drawable/vol.png | Bin 0 -> 6708 bytes app/src/main/res/drawable/zzz_adm.png | Bin 0 -> 43620 bytes app/src/main/res/drawable/zzz_lw.png | Bin 0 -> 80549 bytes app/src/main/res/drawable/zzz_ms.png | Bin 0 -> 72460 bytes app/src/main/res/drawable/zzz_qdb.png | Bin 0 -> 117862 bytes app/src/main/res/drawable/zzz_rev.png | Bin 0 -> 47209 bytes app/src/main/res/drawable/zzz_revl.png | Bin 0 -> 66969 bytes app/src/main/res/drawable/zzz_tesv.png | Bin 0 -> 30593 bytes app/src/main/res/layout/activity_comments.xml | 25 + .../main/res/layout/activity_crash_error.xml | 55 + app/src/main/res/layout/activity_dms.xml | 19 + app/src/main/res/layout/activity_follow.xml | 31 + app/src/main/res/layout/activity_login.xml | 44 + app/src/main/res/layout/activity_main.xml | 311 ++++ app/src/main/res/layout/activity_profile.xml | 37 + .../main/res/layout/activity_story_viewer.xml | 62 + app/src/main/res/layout/activity_viewer.xml | 105 ++ app/src/main/res/layout/dialog_direct.xml | 21 + .../main/res/layout/dialog_import_export.xml | 230 +++ app/src/main/res/layout/dialog_main_about.xml | 67 + .../main/res/layout/dialog_main_settings.xml | 326 +++++ .../res/layout/dialog_profile_settings.xml | 48 + .../main/res/layout/dialog_quick_access.xml | 100 ++ .../main/res/layout/dialog_time_settings.xml | 182 +++ app/src/main/res/layout/header_follow.xml | 36 + app/src/main/res/layout/item_child_post.xml | 36 + app/src/main/res/layout/item_comment.xml | 30 + .../main/res/layout/item_comment_small.xml | 105 ++ app/src/main/res/layout/item_dir_list.xml | 15 + app/src/main/res/layout/item_feed.xml | 17 + app/src/main/res/layout/item_feed_bottom.xml | 138 ++ app/src/main/res/layout/item_feed_slider.xml | 38 + app/src/main/res/layout/item_feed_top.xml | 35 + app/src/main/res/layout/item_feed_video.xml | 23 + app/src/main/res/layout/item_follow.xml | 44 + app/src/main/res/layout/item_highlight.xml | 30 + app/src/main/res/layout/item_message_item.xml | 256 ++++ app/src/main/res/layout/item_post.xml | 55 + app/src/main/res/layout/item_story.xml | 29 + app/src/main/res/layout/item_suggestion.xml | 52 + .../res/layout/layout_changelog_textview.xml | 18 + app/src/main/res/layout/layout_controls.xml | 25 + .../res/layout/layout_directory_chooser.xml | 115 ++ .../layout_include_custom_format_info.xml | 276 ++++ .../res/layout/layout_include_simple_item.xml | 135 ++ .../res/layout/layout_include_toolbar.xml | 19 + app/src/main/res/layout/layout_password.xml | 11 + app/src/main/res/layout/layout_searchview.xml | 4 + app/src/main/res/menu/follow.xml | 20 + app/src/main/res/menu/menu.xml | 55 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2988 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 6380 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1786 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 3539 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4471 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 9899 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 8646 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 18302 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 12949 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 28585 bytes app/src/main/res/values-es/arrays.xml | 19 + app/src/main/res/values-es/strings.xml | 147 ++ app/src/main/res/values-fr/arrays.xml | 28 + app/src/main/res/values-fr/strings.xml | 147 ++ app/src/main/res/values-in/arrays.xml | 28 + app/src/main/res/values-in/strings.xml | 147 ++ app/src/main/res/values-it/arrays.xml | 28 + app/src/main/res/values-it/strings.xml | 147 ++ app/src/main/res/values-land/dimens.xml | 13 + app/src/main/res/values-night/bool.xml | 4 + app/src/main/res/values-night/color.xml | 6 + app/src/main/res/values-night/styles.xml | 7 + app/src/main/res/values-zh/arrays.xml | 28 + app/src/main/res/values-zh/strings.xml | 147 ++ app/src/main/res/values/arrays.xml | 91 ++ app/src/main/res/values/bool.xml | 4 + app/src/main/res/values/color.xml | 20 + app/src/main/res/values/dimens.xml | 19 + app/src/main/res/values/strings.xml | 169 +++ app/src/main/res/values/styles.xml | 37 + app/src/main/res/xml/backup_descriptor.xml | 3 + app/src/main/res/xml/provider_paths.xml | 6 + app/web_hi_res_512.png | Bin 0 -> 135209 bytes build.gradle | 23 + gradle.properties | 20 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 172 +++ gradlew.bat | 84 ++ settings.gradle | 2 + 275 files changed, 22638 insertions(+) create mode 100755 .gitignore create mode 100755 .gitlab-ci.yml create mode 100644 .idea/.name create mode 100755 .idea/codeStyles create mode 100755 .idea/gradle.xml create mode 100755 .idea/inspectionProfiles/profiles_settings.xml create mode 100755 .idea/jarRepositories.xml create mode 100755 .idea/misc.xml create mode 100755 .idea/render.experimental.xml create mode 100755 .idea/runConfigurations.xml create mode 100755 .idea/runConfigurations/app.xml create mode 100755 .idea/vcs.xml create mode 100755 CHANGELOG create mode 100755 LICENSE create mode 100755 README.md create mode 100755 app/.gitignore create mode 100755 app/build.gradle create mode 100755 app/lint.xml create mode 100755 app/play_icon.png create mode 100755 app/proguard-rules.pro create mode 100755 app/src/main/AndroidManifest.xml create mode 100755 app/src/main/ic_launcher-playstore.png create mode 100755 app/src/main/java/awais/instagrabber/InstaApp.java create mode 100755 app/src/main/java/awais/instagrabber/MainHelper.java create mode 100755 app/src/main/java/awais/instagrabber/activities/BaseLanguageActivity.java create mode 100755 app/src/main/java/awais/instagrabber/activities/CommentsViewer.java create mode 100755 app/src/main/java/awais/instagrabber/activities/DirectMessages.java create mode 100755 app/src/main/java/awais/instagrabber/activities/DirectMessagesUserInbox.java create mode 100755 app/src/main/java/awais/instagrabber/activities/FollowViewer.java create mode 100755 app/src/main/java/awais/instagrabber/activities/Login.java create mode 100755 app/src/main/java/awais/instagrabber/activities/Main.java create mode 100755 app/src/main/java/awais/instagrabber/activities/PostViewer.java create mode 100755 app/src/main/java/awais/instagrabber/activities/ProfileViewer.java create mode 100755 app/src/main/java/awais/instagrabber/activities/StoryViewer.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/CommentsAdapter.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/DirectMessagesAdapter.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/DiscoverAdapter.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/FeedAdapter.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/FeedStoriesAdapter.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/FollowAdapter.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/HighlightsAdapter.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/MessageItemsAdapter.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/PostsAdapter.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/PostsMediaAdapter.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/SimpleAdapter.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/StoriesAdapter.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/SuggestionsAdapter.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/viewholder/CommentViewHolder.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/viewholder/DirectMessageViewHolder.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/viewholder/DiscoverViewHolder.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/viewholder/FeedItemViewHolder.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/viewholder/FollowsViewHolder.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/viewholder/HighlightViewHolder.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/viewholder/PostMediaViewHolder.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/viewholder/PostViewHolder.java create mode 100755 app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/TextMessageViewHolder.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/CommentsFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/DiscoverFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/DownloadAsync.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/FeedFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/FeedStoriesFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/FollowFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/HighlightsFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/ProfilePictureFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/StoryStatusFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/SuggestionsFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/UsernameFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/direct_messages/InboxFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/asyncs/direct_messages/UserInboxFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/customviews/CircularImageView.java create mode 100755 app/src/main/java/awais/instagrabber/customviews/CommentMentionClickSpan.java create mode 100755 app/src/main/java/awais/instagrabber/customviews/FixedImageView.java create mode 100755 app/src/main/java/awais/instagrabber/customviews/MouseDrawer.java create mode 100755 app/src/main/java/awais/instagrabber/customviews/RamboTextView.java create mode 100755 app/src/main/java/awais/instagrabber/customviews/RemixDrawerLayout.java create mode 100755 app/src/main/java/awais/instagrabber/customviews/helpers/GridAutofitLayoutManager.java create mode 100755 app/src/main/java/awais/instagrabber/customviews/helpers/GridSpacingItemDecoration.java create mode 100755 app/src/main/java/awais/instagrabber/customviews/helpers/RecyclerLazyLoader.java create mode 100755 app/src/main/java/awais/instagrabber/customviews/helpers/SwipeGestureListener.java create mode 100755 app/src/main/java/awais/instagrabber/customviews/helpers/VideoAwareRecyclerScroller.java create mode 100755 app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/SoundParser.java create mode 100755 app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/WaveFormProgressChangeListener.java create mode 100755 app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/WaveGravity.java create mode 100755 app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/WaveformSeekBar.java create mode 100755 app/src/main/java/awais/instagrabber/dialogs/AboutDialog.java create mode 100755 app/src/main/java/awais/instagrabber/dialogs/ProfileSettingsDialog.java create mode 100755 app/src/main/java/awais/instagrabber/dialogs/QuickAccessDialog.java create mode 100755 app/src/main/java/awais/instagrabber/dialogs/SettingsDialog.java create mode 100755 app/src/main/java/awais/instagrabber/dialogs/TimeSettingsDialog.java create mode 100755 app/src/main/java/awais/instagrabber/directdownload/DirectDownload.java create mode 100755 app/src/main/java/awais/instagrabber/directdownload/MultiDirectDialog.java create mode 100755 app/src/main/java/awais/instagrabber/interfaces/FetchListener.java create mode 100755 app/src/main/java/awais/instagrabber/interfaces/ItemGetter.java create mode 100755 app/src/main/java/awais/instagrabber/interfaces/LazyLoadListener.java create mode 100755 app/src/main/java/awais/instagrabber/interfaces/MentionClickListener.java create mode 100755 app/src/main/java/awais/instagrabber/interfaces/OnGroupClickListener.java create mode 100755 app/src/main/java/awais/instagrabber/interfaces/SwipeEvent.java create mode 100755 app/src/main/java/awais/instagrabber/models/BasePostModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/CommentModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/DiscoverItemModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/FeedModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/FeedStoryModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/FollowModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/HighlightModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/IntentModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/PostModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/ProfileModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/StoryModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/SuggestionModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/ViewerPostModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/direct_messages/DirectItemModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/direct_messages/InboxMediaModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/direct_messages/InboxModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/direct_messages/InboxThreadModel.java create mode 100755 app/src/main/java/awais/instagrabber/models/enums/DirectItemType.java create mode 100755 app/src/main/java/awais/instagrabber/models/enums/DownloadMethod.java create mode 100755 app/src/main/java/awais/instagrabber/models/enums/InboxReadState.java create mode 100755 app/src/main/java/awais/instagrabber/models/enums/IntentModelType.java create mode 100755 app/src/main/java/awais/instagrabber/models/enums/ItemGetType.java create mode 100755 app/src/main/java/awais/instagrabber/models/enums/MediaItemType.java create mode 100755 app/src/main/java/awais/instagrabber/models/enums/ProfilePictureFetchMode.java create mode 100755 app/src/main/java/awais/instagrabber/models/enums/RavenExpiringMediaType.java create mode 100755 app/src/main/java/awais/instagrabber/models/enums/RavenMediaViewType.java create mode 100755 app/src/main/java/awais/instagrabber/models/enums/SuggestionType.java create mode 100755 app/src/main/java/awais/instagrabber/models/enums/UserInboxDirection.java create mode 100755 app/src/main/java/awais/instagrabber/utils/ChangelogFetcher.java create mode 100755 app/src/main/java/awais/instagrabber/utils/Constants.java create mode 100755 app/src/main/java/awais/instagrabber/utils/DataBox.java create mode 100755 app/src/main/java/awais/instagrabber/utils/DirectoryChooser.java create mode 100755 app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java create mode 100755 app/src/main/java/awais/instagrabber/utils/FlavorTown.java create mode 100755 app/src/main/java/awais/instagrabber/utils/LocaleUtils.java create mode 100755 app/src/main/java/awais/instagrabber/utils/MyApps.java create mode 100755 app/src/main/java/awais/instagrabber/utils/SettingsHelper.java create mode 100755 app/src/main/java/awais/instagrabber/utils/UpdateChecker.java create mode 100755 app/src/main/java/awais/instagrabber/utils/UrlEncoder.java create mode 100755 app/src/main/java/awais/instagrabber/utils/Utils.java create mode 100755 app/src/main/java/awaisomereport/CrashReporter.java create mode 100755 app/src/main/java/awaisomereport/ErrorReporterActivity.java create mode 100755 app/src/main/java/awaisomereport/LogCollector.java create mode 100755 app/src/main/java/thoughtbot/expandableadapter/ExpandableGroup.java create mode 100755 app/src/main/java/thoughtbot/expandableadapter/ExpandableList.java create mode 100755 app/src/main/java/thoughtbot/expandableadapter/ExpandableListPosition.java create mode 100755 app/src/main/java/thoughtbot/expandableadapter/GroupViewHolder.java create mode 100755 app/src/main/res/drawable-hdpi/ic_download.png~ create mode 100755 app/src/main/res/drawable-hdpi/nav_up.png create mode 100755 app/src/main/res/drawable-mdpi/ic_download.png~ create mode 100755 app/src/main/res/drawable-mdpi/nav_up.png create mode 100755 app/src/main/res/drawable-night-hdpi/nav_up.png create mode 100755 app/src/main/res/drawable-night-mdpi/nav_up.png create mode 100755 app/src/main/res/drawable-night-xhdpi/nav_up.png create mode 100755 app/src/main/res/drawable-night-xxhdpi/nav_up.png create mode 100755 app/src/main/res/drawable-night/collapse.png create mode 100755 app/src/main/res/drawable-night/comments.png create mode 100755 app/src/main/res/drawable-night/expand.png create mode 100755 app/src/main/res/drawable-night/expired.png create mode 100755 app/src/main/res/drawable-night/mute.png create mode 100755 app/src/main/res/drawable-night/video_views.png create mode 100755 app/src/main/res/drawable-night/vol.png create mode 100755 app/src/main/res/drawable-xhdpi/nav_up.png create mode 100755 app/src/main/res/drawable-xxhdpi/nav_up.png create mode 100755 app/src/main/res/drawable/check.png create mode 100755 app/src/main/res/drawable/collapse.png create mode 100755 app/src/main/res/drawable/comments.png create mode 100755 app/src/main/res/drawable/downloaded.png create mode 100755 app/src/main/res/drawable/expand.png create mode 100755 app/src/main/res/drawable/expired.png create mode 100755 app/src/main/res/drawable/ic_add.xml create mode 100755 app/src/main/res/drawable/ic_discover.xml create mode 100755 app/src/main/res/drawable/ic_download.xml create mode 100755 app/src/main/res/drawable/ic_feed.xml create mode 100755 app/src/main/res/drawable/ic_fullscreen.xml create mode 100755 app/src/main/res/drawable/ic_fullscreen_exit.xml create mode 100755 app/src/main/res/drawable/ic_import_export.xml create mode 100755 app/src/main/res/drawable/ic_profile.xml create mode 100755 app/src/main/res/drawable/lock.xml create mode 100755 app/src/main/res/drawable/mute.png create mode 100755 app/src/main/res/drawable/slider.png create mode 100755 app/src/main/res/drawable/verified.png create mode 100755 app/src/main/res/drawable/video.png create mode 100755 app/src/main/res/drawable/video_views.png create mode 100755 app/src/main/res/drawable/vol.png create mode 100755 app/src/main/res/drawable/zzz_adm.png create mode 100755 app/src/main/res/drawable/zzz_lw.png create mode 100755 app/src/main/res/drawable/zzz_ms.png create mode 100755 app/src/main/res/drawable/zzz_qdb.png create mode 100755 app/src/main/res/drawable/zzz_rev.png create mode 100755 app/src/main/res/drawable/zzz_revl.png create mode 100755 app/src/main/res/drawable/zzz_tesv.png create mode 100755 app/src/main/res/layout/activity_comments.xml create mode 100755 app/src/main/res/layout/activity_crash_error.xml create mode 100755 app/src/main/res/layout/activity_dms.xml create mode 100755 app/src/main/res/layout/activity_follow.xml create mode 100755 app/src/main/res/layout/activity_login.xml create mode 100755 app/src/main/res/layout/activity_main.xml create mode 100755 app/src/main/res/layout/activity_profile.xml create mode 100755 app/src/main/res/layout/activity_story_viewer.xml create mode 100755 app/src/main/res/layout/activity_viewer.xml create mode 100755 app/src/main/res/layout/dialog_direct.xml create mode 100755 app/src/main/res/layout/dialog_import_export.xml create mode 100755 app/src/main/res/layout/dialog_main_about.xml create mode 100755 app/src/main/res/layout/dialog_main_settings.xml create mode 100755 app/src/main/res/layout/dialog_profile_settings.xml create mode 100755 app/src/main/res/layout/dialog_quick_access.xml create mode 100755 app/src/main/res/layout/dialog_time_settings.xml create mode 100755 app/src/main/res/layout/header_follow.xml create mode 100755 app/src/main/res/layout/item_child_post.xml create mode 100755 app/src/main/res/layout/item_comment.xml create mode 100755 app/src/main/res/layout/item_comment_small.xml create mode 100755 app/src/main/res/layout/item_dir_list.xml create mode 100755 app/src/main/res/layout/item_feed.xml create mode 100755 app/src/main/res/layout/item_feed_bottom.xml create mode 100755 app/src/main/res/layout/item_feed_slider.xml create mode 100755 app/src/main/res/layout/item_feed_top.xml create mode 100755 app/src/main/res/layout/item_feed_video.xml create mode 100755 app/src/main/res/layout/item_follow.xml create mode 100755 app/src/main/res/layout/item_highlight.xml create mode 100755 app/src/main/res/layout/item_message_item.xml create mode 100755 app/src/main/res/layout/item_post.xml create mode 100755 app/src/main/res/layout/item_story.xml create mode 100755 app/src/main/res/layout/item_suggestion.xml create mode 100755 app/src/main/res/layout/layout_changelog_textview.xml create mode 100755 app/src/main/res/layout/layout_controls.xml create mode 100755 app/src/main/res/layout/layout_directory_chooser.xml create mode 100755 app/src/main/res/layout/layout_include_custom_format_info.xml create mode 100755 app/src/main/res/layout/layout_include_simple_item.xml create mode 100755 app/src/main/res/layout/layout_include_toolbar.xml create mode 100755 app/src/main/res/layout/layout_password.xml create mode 100755 app/src/main/res/layout/layout_searchview.xml create mode 100755 app/src/main/res/menu/follow.xml create mode 100755 app/src/main/res/menu/menu.xml create mode 100755 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100755 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100755 app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100755 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100755 app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100755 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100755 app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100755 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100755 app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100755 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100755 app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100755 app/src/main/res/values-es/arrays.xml create mode 100755 app/src/main/res/values-es/strings.xml create mode 100755 app/src/main/res/values-fr/arrays.xml create mode 100755 app/src/main/res/values-fr/strings.xml create mode 100755 app/src/main/res/values-in/arrays.xml create mode 100755 app/src/main/res/values-in/strings.xml create mode 100755 app/src/main/res/values-it/arrays.xml create mode 100755 app/src/main/res/values-it/strings.xml create mode 100755 app/src/main/res/values-land/dimens.xml create mode 100755 app/src/main/res/values-night/bool.xml create mode 100755 app/src/main/res/values-night/color.xml create mode 100755 app/src/main/res/values-night/styles.xml create mode 100755 app/src/main/res/values-zh/arrays.xml create mode 100755 app/src/main/res/values-zh/strings.xml create mode 100755 app/src/main/res/values/arrays.xml create mode 100755 app/src/main/res/values/bool.xml create mode 100755 app/src/main/res/values/color.xml create mode 100755 app/src/main/res/values/dimens.xml create mode 100755 app/src/main/res/values/strings.xml create mode 100755 app/src/main/res/values/styles.xml create mode 100755 app/src/main/res/xml/backup_descriptor.xml create mode 100755 app/src/main/res/xml/provider_paths.xml create mode 100755 app/web_hi_res_512.png create mode 100755 build.gradle create mode 100755 gradle.properties create mode 100755 gradle/wrapper/gradle-wrapper.jar create mode 100755 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100755 gradlew.bat create mode 100755 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100755 index 00000000..825ad741 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/markdown-navigator.xml +/.idea/markdown-navigator-enh.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100755 index 00000000..24e1e984 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,54 @@ +image: openjdk:8-jdk + +variables: + ANDROID_COMPILE_SDK: "29" + ANDROID_BUILD_TOOLS: "29.0.2" + ANDROID_SDK_TOOLS: "4333796" + +before_script: + # - export vercode=$(cat ./app/build.gradle | grep versionName) + # - export vercode=$(echo $vercode | awk -F[=\'] '{print $2}') + # - echo $vercode > vercode.txt + - apt-get --quiet update --yes + - apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1 + - if [ -f "android-sdk.zip" ]; then echo "exists!!" ; else wget --quiet --output-document=android-sdk.zip https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_TOOLS}.zip ; fi + - unzip -d android-sdk-linux android-sdk.zip + - echo y | android-sdk-linux/tools/bin/sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}" >/dev/null + - echo y | android-sdk-linux/tools/bin/sdkmanager "platform-tools" >/dev/null + - echo y | android-sdk-linux/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS}" >/dev/null + - export ANDROID_HOME=$PWD/android-sdk-linux + - export PATH=$PATH:$PWD/android-sdk-linux/platform-tools/ + - chmod +x ./gradlew + - set +o pipefail + - yes | android-sdk-linux/tools/bin/sdkmanager --licenses + - set -o pipefail + +stages: + - release + + +# lintDebug: +# stage: build +# script: +# - ./gradlew -Pci --console=plain :app:lintDebug -PbuildDir=lint + +assembleDebug: + stage: release + script: + - ./gradlew assembleDebug + artifacts: + expire_in: 4 days + paths: + - app/build/outputs/ + +# assembleRelease: +# stage: release +# script: +# - ./gradlew assembleRelease +# -Pandroid.injected.signing.store.file=$(pwd)/.RELEASE.jks +# -Pandroid.injected.signing.store.password=$PSWD +# -Pandroid.injected.signing.key.alias=$AIZA +# -Pandroid.injected.signing.key.password=$PSWD +# artifacts: +# paths: +# - app/build/outputs/ diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 00000000..0e33933c --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +InstaGrabber \ No newline at end of file diff --git a/.idea/codeStyles b/.idea/codeStyles new file mode 100755 index 00000000..e2e415d5 --- /dev/null +++ b/.idea/codeStyles @@ -0,0 +1,119 @@ + + + + + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:name + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + name + + ^$ + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .* + + http://schemas.android.com/apk/res/android + + + ANDROID_ATTRIBUTE_ORDER + +
+
+ + + + .* + + .* + + + BY_NAME + +
+
+
+
+
+
+
\ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100755 index 00000000..ac6b0aec --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100755 index 00000000..dd4c951e --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100755 index 00000000..247f71d9 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100755 index 00000000..3ea378e6 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/render.experimental.xml b/.idea/render.experimental.xml new file mode 100755 index 00000000..8ec256a5 --- /dev/null +++ b/.idea/render.experimental.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100755 index 00000000..7f68460d --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/app.xml b/.idea/runConfigurations/app.xml new file mode 100755 index 00000000..aeebe8e5 --- /dev/null +++ b/.idea/runConfigurations/app.xml @@ -0,0 +1,53 @@ + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100755 index 00000000..35eb1ddf --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CHANGELOG b/CHANGELOG new file mode 100755 index 00000000..6c29fcd6 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,193 @@ + +v15.9 +note: there will be no F-Droid updates from this version (v15.9) and onward, download updates from repo's Releases page. + ++ added user stories in Feed ++ added frame to currently showing slider item ++ removed tap to pause/resume from Post viewer, replaced with controller ++ fixed swipe not working when posts are opened from stories ++ fixed comments not showing for slider items + +v15.8 ++ added user's website in profile ++ fixed caption mentions length (@kernoeb) ++ fixed some translations (@kernoeb) ++ fixd feed captions merging with "... more" + +v15.4 ++ ADDED FRENCH AND SPANISH!!! ++-> Huge thanks to @kernoeb (Telegram) for French translation and @sguinetti (GitLab) for Spanish translation!! + ++ added custom post time format support! ++ fixed flickering after changing settings ++ fixed posts not showing after searching from a private profile ++ fixed stories and profile pictures not downloading in user folders even when option was enabled ++ fixed issues with feed, discover and post viewer ++ fixed search suggestions crashes + +v15.2 ++ fixed feed video not pausing when opened in post viewer ++ added 1 new profile picture view mode ++ added fields in LogCollector to better understand how things went wrong ++ better comments, story, feed, discover and suggestion fetchers + +v15.0 ++ added support for Instagram.com urls! (: ++ added "Downloaded" check on posts if they've already been downloaded (as per suggestion) ++ fixed highlights scrolling issues ++ fixed comments issues ++ fixed posts weren't showing after searching anything from a private account ++ fixed suggestions not showing sometimes ++ fixed Stories viewer swipe issues ++ fixed Import/Export dialog not showing on old phones ++ added user's name in suggestions search list ++ added comment likes in Comments viewer + ++ sending logs won't add empty logs to archive anymore! ++ fixed no new line in logs ++ handled Login WebView lifecycles ++ a better way of handling highlight swipes ++ removed useless code parts + +v14.5 ++ added changelog after update ++ added swipe support in both Discover/Explore and Feed pages ++ added Send Logs button in Settings to send logs when something doesn't work ++ added clickable user profile in Post Viewer ++ fixed weirdly collapsing toolbar when toolbar is shown at the top + +v14.0 ++ added theme selection support ++ added import/export settings, favorites and logins functionality (thanks to Airikr [@edgren] on Telegram) ++ added support for downloading slider items from User Feed page ++ added support for usernames and hashtags in user's biography/about text ++ added multiple selection in Discover/Explore page ++ added post date for feed items ++ added some more date formats ++ copyable feed item caption (long tap) ++ fixed late refresh indicator in Followers/Following comparison mode ++ changed feed item size to squares ++ fixed some caption text issues having mentions and hashtags ++ removed clipboard listener (stopped working after some changes) ++ added log collector for different crash scenarios + +v13.7 ++ fixed custom download folder selection issues + +v13.3 ++ added discover/explore page (only for logged in users) ++ added function to remove IPTC tracking data from downloaded pictures (thanks to Airikr [@edgren] on Telegram) ++ added multiple accounts support (quick access) and favorites (a suggestion from Saurabh on Telegram) ++ added custom download folder option, you can select where to download posts (a suggestion from Airikr) ++ added desktop mode toggle in Login activity (a suggestion from Eymen on Telegram) ++ added post date in post viewer (a suggestion from W on Telegram) ++ added post time format settings [ Settings > Post Time Settings ] ++ fixed some icons and layouts ++ removed color from slider items in feed ++ removed useless methods and properties ++ better way of handling multiple stories and posts (sliders) in post viewer ++ tried to make notifications grouped together.. hope they work ++ some other fixes and additions which i probably forgot, cause i'm a human ffs + +v13.0 ++ fixed crash when searching hashtags ++ added lazy loading for hashtags ++ added Show Feed option in Settings (feed may crash app on some phones) ++ added null check in Download async ++ better/adapatable icon ++ fixed sheet dialog themes + +v12.7 ++ (probably) fixed inflating issue in some devices + +v12.5 ++ some small performance improvements + +v12.0 ++ added feed!! (only for logged in users) ++ fixed multiple hashtags with no spaces between them ++ stopped activity from recreating when nothing changed ++ changed highlights to RecyclerView instead of HorizontalScrollView ++ changed some numbers and precisions cause she left me on read + +v11.0 ++ added crash reporting library ++ added mute/unmute for session ++ better profile picture viewer + profile picture info ++ better swipe gesture ++ fixed mention and hashtag issues + +v10.0 +NOTE: YOU MAY NEED TO LOGIN TO VIEW PROFILES CAUSE OF INSTAGRAM CHANGES. ++ added direct download multiple posts dialog ++ fixed notification problems ++ fixed some direct download problems ++ fixed batch download and username folder not creating in some activities ++ fixed update checker + +v9.0 ++ added search in comments viewer ++ added settings to auto or lazy load posts ++ added user & hashtag stack when back pressed ++ added loading icon when loading posts ++ profile info bar sticks to top ++ fixed highlights and profile picture size in portrait and landscape mode ++ fixed posts loading from other user when restarting app ++ fixed posts size changing when scrolled ++ users & hashtag search shows only users or hashtag when first char is @ or # ++ scrolls to top when back pressed + +v8.0 ++ added pull-to-refresh layout in main posts, followers/following viewer ++ added search in followers/following viewer ++ added video views in post viewer ++ added animation when showing highlights (if available) ++ fixed long usernames not animating (marquee) ++ fixed padding and size in portrait and landscape modes ++ fixed accounts showing personal followers/following when account has 0 followers/following ++ fixed double ripple when tapped on profile picture ++ smaller story border around profile picture + +v7.0 ++ added comments viewer!! ++ added highest quality post fetcher ++ added loading indicator where it was missing before ++ fixed highlight name alignment ++ fixed swiping on posts opened via Share or link + +v6.0 ++ added story highlights!! (issue #5) ++ added button to view posts posted in stories ++ added verified badge for accounts ++ fixed posts & story swiping issues ++ fixed slow loading and stuff ++ fixed different margins and sizes ++ fixed activity not recreating after settings dialogs closed + +v5.0 ++ added followers / following checker ++ added search view suggestions for usernames & hashtags ++ added sliding profile container ++ fixed batch download permission issue (issue #4) ++ fixed some small screen panning issues ++ fixed search view width ++ fixed update checker + +v4.0 ++ fixed Login and Visit project page button codes. + +v3.0 ++ fixed posts merged from different accounts when searched while posts are loading! ++ view stories (only if you're logged in) ++ directly download posts ++ choose between two pfp (profile picture) viewer methods ++ fixed search box not showing up when toolbar is at bottom ++ automatically checks for updates + +v2.0 ++ fixed Login crashes + +v1.0 ++ first ever changelog ++ basic stuff like downloading profile pics, posts and copying captions and bio. ++ batch download posts diff --git a/LICENSE b/LICENSE new file mode 100755 index 00000000..3c8b32d8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + InstaGrabber + Copyright (C) 2019 AWAiS + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + InstaGrabber Copyright (C) 2019 AWAiS + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100755 index 00000000..66a4ac64 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +![InstaGrabber](./app/src/main/res/mipmap-hdpi/ic_launcher.png "InstaGrabber") InstaGrabber + +Revived Version by Austin. + +Coming soon™ \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100755 index 00000000..796b96d1 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100755 index 00000000..d7e73113 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,50 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 29 + + defaultConfig { + applicationId 'awais.instagrabber' + + minSdkVersion 16 + targetSdkVersion 29 + + versionCode 27 + versionName '16.5-a1' + + multiDexEnabled true + + vectorDrawables.useSupportLibrary = true + vectorDrawables.generatedDensities = [] + } + + compileOptions { + targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_1_8 + } + + buildFeatures { viewBinding true } + + aaptOptions { additionalParameters '--no-version-vectors' } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation('androidx.appcompat:appcompat:1.3.0-alpha01@aar') { transitive true } + implementation('androidx.recyclerview:recyclerview:1.2.0-alpha03@aar') { transitive true } + implementation('com.google.android.material:material:1.3.0-alpha01@aar') { transitive true } + implementation('androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-rc01') { transitive true } + + annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' + + implementation('org.jsoup:jsoup:1.13.1') { transitive true } + implementation('com.github.bumptech.glide:glide:4.11.0') { transitive true } + implementation('com.github.chrisbanes:PhotoView:v2.0.0@aar') { transitive true } + implementation('com.google.android.exoplayer:exoplayer:2.11.1@aar') { transitive true } +} diff --git a/app/lint.xml b/app/lint.xml new file mode 100755 index 00000000..8fb95bdc --- /dev/null +++ b/app/lint.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/play_icon.png b/app/play_icon.png new file mode 100755 index 0000000000000000000000000000000000000000..b06c141b07d9e7e839495b9fe8eae89ad287010f GIT binary patch literal 145258 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 literal 0 HcmV?d00001 diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100755 index 00000000..f1b42451 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100755 index 00000000..613d579d --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png new file mode 100755 index 0000000000000000000000000000000000000000..714fd9cf11969803a73a22e982312ec70f7c0dfc GIT binary patch literal 71824 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 MTbJ_<=K^p18`U;bZ~y=R literal 0 HcmV?d00001 diff --git a/app/src/main/java/awais/instagrabber/InstaApp.java b/app/src/main/java/awais/instagrabber/InstaApp.java new file mode 100755 index 00000000..260eeeaf --- /dev/null +++ b/app/src/main/java/awais/instagrabber/InstaApp.java @@ -0,0 +1,66 @@ +package awais.instagrabber; + +import android.content.ClipboardManager; +import android.content.Context; + +import androidx.core.app.NotificationManagerCompat; +import androidx.multidex.MultiDexApplication; + +import java.net.CookieHandler; +import java.text.SimpleDateFormat; + +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.DataBox; +import awais.instagrabber.utils.LocaleUtils; +import awais.instagrabber.utils.SettingsHelper; +import awaisomereport.CrashReporter; +import awaisomereport.LogCollector; + +import static awais.instagrabber.utils.Utils.NET_COOKIE_MANAGER; +import static awais.instagrabber.utils.Utils.changeTheme; +import static awais.instagrabber.utils.Utils.clipboardManager; +import static awais.instagrabber.utils.Utils.dataBox; +import static awais.instagrabber.utils.Utils.datetimeParser; +import static awais.instagrabber.utils.Utils.getInstalledTelegramPackage; +import static awais.instagrabber.utils.Utils.isInstaInstalled; +import static awais.instagrabber.utils.Utils.isInstagramInstalled; +import static awais.instagrabber.utils.Utils.logCollector; +import static awais.instagrabber.utils.Utils.notificationManager; +import static awais.instagrabber.utils.Utils.settingsHelper; +import static awais.instagrabber.utils.Utils.telegramPackage; + +public final class InstaApp extends MultiDexApplication { + @Override + public void onCreate() { + super.onCreate(); + + if (!BuildConfig.DEBUG) CrashReporter.get(this).start(); + logCollector = new LogCollector(this); + + CookieHandler.setDefault(NET_COOKIE_MANAGER); + + final Context appContext = getApplicationContext(); + + isInstagramInstalled = isInstaInstalled(appContext); + telegramPackage = getInstalledTelegramPackage(appContext); + + if (dataBox == null) + dataBox = DataBox.getInstance(appContext); + + if (settingsHelper == null) + settingsHelper = new SettingsHelper(this); + + LocaleUtils.setLocale(getBaseContext()); + + if (notificationManager == null) + notificationManager = NotificationManagerCompat.from(appContext); + + if (clipboardManager == null) + clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + + if (datetimeParser == null) + datetimeParser = new SimpleDateFormat(settingsHelper.getString(Constants.DATE_TIME_FORMAT), LocaleUtils.getCurrentLocale()); + + changeTheme(); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/MainHelper.java b/app/src/main/java/awais/instagrabber/MainHelper.java new file mode 100755 index 00000000..20193206 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/MainHelper.java @@ -0,0 +1,864 @@ +package awais.instagrabber; + +import android.content.Intent; +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Handler; +import android.text.SpannableStringBuilder; +import android.text.method.LinkMovementMethod; +import android.text.style.RelativeSizeSpan; +import android.text.style.StyleSpan; +import android.util.Log; +import android.util.TypedValue; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.core.content.ContextCompat; +import androidx.core.view.GravityCompat; +import androidx.core.widget.ImageViewCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.shape.MaterialShapeDrawable; + +import java.util.Arrays; + +import awais.instagrabber.activities.FollowViewer; +import awais.instagrabber.activities.Main; +import awais.instagrabber.activities.PostViewer; +import awais.instagrabber.activities.StoryViewer; +import awais.instagrabber.adapters.DiscoverAdapter; +import awais.instagrabber.adapters.FeedAdapter; +import awais.instagrabber.adapters.FeedStoriesAdapter; +import awais.instagrabber.adapters.PostsAdapter; +import awais.instagrabber.asyncs.DiscoverFetcher; +import awais.instagrabber.asyncs.FeedFetcher; +import awais.instagrabber.asyncs.FeedStoriesFetcher; +import awais.instagrabber.asyncs.HighlightsFetcher; +import awais.instagrabber.asyncs.PostsFetcher; +import awais.instagrabber.asyncs.ProfileFetcher; +import awais.instagrabber.asyncs.StoryStatusFetcher; +import awais.instagrabber.customviews.MouseDrawer; +import awais.instagrabber.customviews.RamboTextView; +import awais.instagrabber.customviews.helpers.GridAutofitLayoutManager; +import awais.instagrabber.customviews.helpers.GridSpacingItemDecoration; +import awais.instagrabber.customviews.helpers.RecyclerLazyLoader; +import awais.instagrabber.customviews.helpers.VideoAwareRecyclerScroller; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.interfaces.MentionClickListener; +import awais.instagrabber.models.BasePostModel; +import awais.instagrabber.models.DiscoverItemModel; +import awais.instagrabber.models.FeedModel; +import awais.instagrabber.models.FeedStoryModel; +import awais.instagrabber.models.IntentModel; +import awais.instagrabber.models.PostModel; +import awais.instagrabber.models.StoryModel; +import awais.instagrabber.models.enums.IntentModelType; +import awais.instagrabber.models.enums.ItemGetType; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; +import awaisomereport.LogCollector; + +import static awais.instagrabber.utils.Constants.AUTOLOAD_POSTS; +import static awais.instagrabber.utils.Constants.BOTTOM_TOOLBAR; +import static awais.instagrabber.utils.Utils.logCollector; + +public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { + private static AsyncTask currentlyExecuting; + private AsyncTask prevStoriesFetcher; + private final boolean autoloadPosts; + private boolean hasNextPage = false, feedHasNextPage = false, discoverHasMore = false; + private String endCursor = null, feedEndCursor = null, discoverEndMaxId = null; + private final FetchListener postsFetchListener = new FetchListener() { + @Override + public void onResult(final PostModel[] result) { + if (result != null) { + final int oldSize = main.allItems.size(); + main.allItems.addAll(Arrays.asList(result)); + + postsAdapter.notifyItemRangeInserted(oldSize, result.length); + + main.mainBinding.mainPosts.post(() -> { + main.mainBinding.mainPosts.setNestedScrollingEnabled(true); + main.mainBinding.mainPosts.setVisibility(View.VISIBLE); + }); + + final String username; + final String postFix; + if (!isHashtag) { + username = main.profileModel.getUsername(); + postFix = "/" + main.profileModel.getPostCount() + ')'; + } else { + username = null; + postFix = null; + } + + if (isHashtag) + main.mainBinding.toolbar.toolbar.setTitle(main.getString(R.string.title_hashtag_prefix) + main.userQuery); + else main.mainBinding.toolbar.toolbar.setTitle(username + " (" + main.allItems.size() + postFix); + + final PostModel model = result[result.length - 1]; + if (model != null) { + endCursor = model.getEndCursor(); + + if (endCursor == null && !isHashtag) { + main.mainBinding.toolbar.toolbar.setTitle(username + " (" + main.profileModel.getPostCount() + postFix); + final Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + main.mainBinding.toolbar.toolbar.setTitle(username); + handler.removeCallbacks(this); + } + }, 1000); + } + + hasNextPage = model.hasNextPage(); + if ((autoloadPosts && hasNextPage) && !isHashtag) + currentlyExecuting = new PostsFetcher(main.profileModel.getId(), endCursor, this) + .setUsername(main.profileModel.getUsername()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + else + main.mainBinding.swipeRefreshLayout.setRefreshing(false); + model.setPageCursor(false, null); + } + } + } + }; + private final FetchListener feedFetchListener = new FetchListener() { + @Override + public void doBefore() { + main.mainBinding.feedSwipeRefreshLayout.post(() -> main.mainBinding.feedSwipeRefreshLayout.setRefreshing(true)); + } + + @Override + public void onResult(final FeedModel[] result) { + if (result != null) { + final int oldSize = main.feedItems.size(); + main.feedItems.addAll(Arrays.asList(result)); + feedAdapter.notifyItemRangeInserted(oldSize, result.length); + + main.mainBinding.feedPosts.post(() -> main.mainBinding.feedPosts.setNestedScrollingEnabled(true)); + + final PostModel feedPostModel = result[result.length - 1]; + if (feedPostModel != null) { + feedEndCursor = feedPostModel.getEndCursor(); + feedHasNextPage = feedPostModel.hasNextPage(); + feedPostModel.setPageCursor(false, null); + } + } + + main.mainBinding.feedSwipeRefreshLayout.setRefreshing(false); + } + }; + private final FetchListener discoverFetchListener = new FetchListener() { + @Override + public void doBefore() { + main.mainBinding.discoverSwipeRefreshLayout.setRefreshing(true); + } + + @Override + public void onResult(final DiscoverItemModel[] result) { + if (result != null) { + final int oldSize = main.discoverItems.size(); + main.discoverItems.addAll(Arrays.asList(result)); + discoverAdapter.notifyItemRangeInserted(oldSize, result.length); + + final DiscoverItemModel discoverItemModel = result[result.length - 1]; + if (discoverItemModel != null) { + discoverEndMaxId = discoverItemModel.getNextMaxId(); + discoverHasMore = discoverItemModel.hasMore(); + discoverItemModel.setMore(false, null); + } + } + + main.mainBinding.discoverSwipeRefreshLayout.setRefreshing(false); + } + }; + private final FetchListener feedStoriesListener = new FetchListener() { + @Override + public void doBefore() { + main.mainBinding.feedStories.setVisibility(View.GONE); + } + + @Override + public void onResult(final FeedStoryModel[] result) { + feedStoriesAdapter.setData(result); + if (result != null && result.length > 0) + main.mainBinding.feedStories.setVisibility(View.VISIBLE); + } + }; + private final MentionClickListener mentionClickListener = new MentionClickListener() { + @Override + public void onClick(final RamboTextView view, final String text, final boolean isHashtag) { + new AlertDialog.Builder(main).setMessage(isHashtag ? R.string.comment_view_mention_hash_search : R.string.comment_view_mention_user_search) + .setTitle(text).setNegativeButton(R.string.cancel, null).setPositiveButton(R.string.ok, (dialog, which) -> { + if (Main.scanHack != null) Main.scanHack.onResult(text); + }).show(); + } + }; + private final FeedStoriesAdapter feedStoriesAdapter = new FeedStoriesAdapter(null, new View.OnClickListener() { + @Override + public void onClick(final View v) { + final Object tag = v.getTag(); + if (tag instanceof FeedStoryModel) { + final FeedStoryModel feedStoryModel = (FeedStoryModel) tag; + final StoryModel[] storyModels = feedStoryModel.getStoryModels(); + + main.startActivity(new Intent(main, StoryViewer.class) + .putExtra(Constants.EXTRAS_STORIES, storyModels) + .putExtra(Constants.EXTRAS_USERNAME, feedStoryModel.getProfileModel().getUsername()) + ); + } + } + }); + @NonNull + private final Main main; + private final Resources resources; + private final View collapsingToolbar; + private final RecyclerLazyLoader lazyLoader; + private boolean isHashtag; + private PostsAdapter postsAdapter; + private FeedAdapter feedAdapter; + private RecyclerLazyLoader feedLazyLoader, discoverLazyLoader; + private DiscoverAdapter discoverAdapter; + public SimpleExoPlayer currentFeedPlayer; // hack for remix drawer layout + + public MainHelper(@NonNull final Main main) { + stopCurrentExecutor(); + + this.main = main; + this.resources = main.getResources(); + this.autoloadPosts = Utils.settingsHelper.getBoolean(AUTOLOAD_POSTS); + + main.mainBinding.swipeRefreshLayout.setOnRefreshListener(this); + main.mainBinding.mainUrl.setMovementMethod(new LinkMovementMethod()); + + final boolean isLoggedIn = !Utils.isEmpty(Utils.settingsHelper.getString(Constants.COOKIE)); + + final LinearLayout iconSlider = main.findViewById(R.id.iconSlider); + final ImageView iconFeed = (ImageView) iconSlider.getChildAt(0); + final ImageView iconProfile = (ImageView) iconSlider.getChildAt(1); + final ImageView iconDiscover = (ImageView) iconSlider.getChildAt(2); + + final boolean isBottomToolbar = Utils.settingsHelper.getBoolean(BOTTOM_TOOLBAR); + if (!isLoggedIn) { + main.mainBinding.drawerLayout.removeView(main.mainBinding.feedLayout); + main.mainBinding.drawerLayout.removeView(main.mainBinding.discoverSwipeRefreshLayout); + iconFeed.setAlpha(0.4f); + iconDiscover.setAlpha(0.4f); + } else { + iconFeed.setAlpha(1f); + iconDiscover.setAlpha(1f); + + setupExplore(); + + final boolean showFeed = Utils.settingsHelper.getBoolean(Constants.SHOW_FEED); + if (showFeed) setupFeed(); + else { + iconFeed.setAlpha(0.4f); + main.mainBinding.drawerLayout.removeView(main.mainBinding.feedLayout); + } + + final TypedValue resolvedAttr = new TypedValue(); + main.getTheme().resolveAttribute(android.R.attr.textColorPrimary, resolvedAttr, true); + + final int selectedItem = ContextCompat.getColor(main, resolvedAttr.resourceId != 0 ? resolvedAttr.resourceId : resolvedAttr.data); + final ColorStateList colorStateList = ColorStateList.valueOf(selectedItem); + + main.mainBinding.toolbar.toolbar.measure(0, -1); + final int toolbarMeasuredHeight = main.mainBinding.toolbar.toolbar.getMeasuredHeight(); + + final ViewGroup.LayoutParams layoutParams = main.mainBinding.toolbar.toolbar.getLayoutParams(); + final MouseDrawer.DrawerListener simpleDrawerListener = new MouseDrawer.DrawerListener() { + private final String titleDiscover = resources.getString(R.string.title_discover); + + @Override + public void onDrawerSlide(final View drawerView, @MouseDrawer.EdgeGravity final int gravity, final float slideOffset) { + final int currentIconAlpha = (int) Math.max(100, 255 - 255 * slideOffset); + final int otherIconAlpha = (int) Math.max(100, 255 * slideOffset); + + ImageViewCompat.setImageTintList(iconProfile, colorStateList.withAlpha(currentIconAlpha)); + + final boolean drawerOpening = slideOffset > 0.0f; + final int alpha; + final ColorStateList imageTintList; + + if (gravity == GravityCompat.START) { + // this helps hide the toolbar when opening feed + + final int roundedToolbarHeight; + final float toolbarHeight; + + if (isBottomToolbar) { + toolbarHeight = toolbarMeasuredHeight * slideOffset; + roundedToolbarHeight = -Math.round(toolbarHeight); + } else { + toolbarHeight = -toolbarMeasuredHeight * slideOffset; + roundedToolbarHeight = Math.round(toolbarHeight); + } + + layoutParams.height = Math.max(0, Math.min(toolbarMeasuredHeight, toolbarMeasuredHeight + roundedToolbarHeight)); + main.mainBinding.toolbar.toolbar.setLayoutParams(layoutParams); + main.mainBinding.toolbar.toolbar.setTranslationY(toolbarHeight); + + imageTintList = ImageViewCompat.getImageTintList(iconDiscover); + alpha = imageTintList != null ? (imageTintList.getDefaultColor() & 0xFF_000000) >> 24 : 0; + + if (drawerOpening && alpha > 100) + ImageViewCompat.setImageTintList(iconDiscover, colorStateList.withAlpha(currentIconAlpha)); + + if (showFeed) ImageViewCompat.setImageTintList(iconFeed, colorStateList.withAlpha(otherIconAlpha)); + } else { + // this changes toolbar title + main.mainBinding.toolbar.toolbar.setTitle(slideOffset >= 0.466 ? titleDiscover : main.userQuery); + + if (showFeed) { + imageTintList = ImageViewCompat.getImageTintList(iconFeed); + alpha = imageTintList != null ? (imageTintList.getDefaultColor() & 0xFF_000000) >> 24 : 0; + + if (drawerOpening && alpha > 100) + ImageViewCompat.setImageTintList(iconFeed, colorStateList.withAlpha(currentIconAlpha)); + } + + ImageViewCompat.setImageTintList(iconDiscover, colorStateList.withAlpha(otherIconAlpha)); + } + } + + @Override + public void onDrawerOpened(@NonNull final View drawerView, @MouseDrawer.EdgeGravity final int gravity) { + if (gravity == GravityCompat.START || drawerView == main.mainBinding.feedLayout) { + if (currentFeedPlayer != null) { + currentFeedPlayer.setPlayWhenReady(true); + currentFeedPlayer.getPlaybackState(); + } + } else { + // clear selection + isSelectionCleared(); + } + } + + @Override + public void onDrawerClosed(@NonNull final View drawerView, @MouseDrawer.EdgeGravity final int gravity) { + if (gravity == GravityCompat.START || drawerView == main.mainBinding.feedLayout) { + if (currentFeedPlayer != null) { + currentFeedPlayer.setPlayWhenReady(false); + currentFeedPlayer.getPlaybackState(); + } + } else { + // clear selection + isSelectionCleared(); + } + } + }; + + ImageViewCompat.setImageTintList(iconFeed, colorStateList.withAlpha(100)); // to change colors when created + ImageViewCompat.setImageTintList(iconProfile, colorStateList.withAlpha(255)); // to change colors when created + ImageViewCompat.setImageTintList(iconDiscover, colorStateList.withAlpha(100)); // to change colors when created + + main.mainBinding.drawerLayout.addDrawerListener(simpleDrawerListener); + } + + collapsingToolbar = main.mainBinding.appBarLayout.getChildAt(0); + + main.mainBinding.mainPosts.setNestedScrollingEnabled(false); + main.mainBinding.highlightsList.setLayoutManager(new LinearLayoutManager(main, LinearLayoutManager.HORIZONTAL, false)); + main.mainBinding.highlightsList.setAdapter(main.highlightsAdapter); + + int color = -1; + final Drawable background = main.mainBinding.appBarLayout.getBackground(); + if (background instanceof MaterialShapeDrawable) { + final MaterialShapeDrawable drawable = (MaterialShapeDrawable) background; + final ColorStateList fillColor = drawable.getFillColor(); + if (fillColor != null) color = fillColor.getDefaultColor(); + } else { + final Bitmap bitmap = Bitmap.createBitmap(9, 9, Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(); + canvas.setBitmap(bitmap); + background.draw(canvas); + color = bitmap.getPixel(4, 4); + if (!bitmap.isRecycled()) bitmap.recycle(); + } + if (color == -1 || color == 0) color = resources.getBoolean(R.bool.isNight) ? 0xff212121 : 0xfff5f5f5; + main.mainBinding.profileInfo.setBackgroundColor(color); + main.mainBinding.profileInfo.setClickable(true); + if (!isBottomToolbar) main.mainBinding.toolbar.toolbar.setBackgroundColor(color); + + main.mainBinding.appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { + private int height; + + @Override + public void onOffsetChanged(final AppBarLayout appBarLayout, final int verticalOffset) { + if (height == 0) { + height = main.mainBinding.profileInfo.getHeight(); + collapsingToolbar.setMinimumHeight(height); + } + main.mainBinding.profileInfo.setTranslationY(-Math.min(0, verticalOffset)); + } + }); + + main.setSupportActionBar(main.mainBinding.toolbar.toolbar); + if (isBottomToolbar) { + final LinearLayout linearLayout = (LinearLayout) main.mainBinding.toolbar.toolbar.getParent(); + linearLayout.removeView(main.mainBinding.toolbar.toolbar); + linearLayout.addView(main.mainBinding.toolbar.toolbar, linearLayout.getChildCount()); + } + + final GridAutofitLayoutManager layoutManager = new GridAutofitLayoutManager(main, Utils.convertDpToPx(130)); + main.mainBinding.mainPosts.setLayoutManager(layoutManager); + main.mainBinding.mainPosts.addItemDecoration(new GridSpacingItemDecoration(Utils.convertDpToPx(4))); + main.mainBinding.mainPosts.setAdapter(postsAdapter = new PostsAdapter(main.allItems, v -> { + final Object tag = v.getTag(); + if (tag instanceof PostModel) { + final PostModel postModel = (PostModel) tag; + + if (postsAdapter.isSelecting) toggleSelection(postModel); + else main.startActivity(new Intent(main, PostViewer.class) + .putExtra(Constants.EXTRAS_INDEX, postModel.getPosition()) + .putExtra(Constants.EXTRAS_POST, postModel) + .putExtra(Constants.EXTRAS_USER, main.userQuery) + .putExtra(Constants.EXTRAS_TYPE, ItemGetType.MAIN_ITEMS)); + } + }, v -> { // long click listener + final Object tag = v.getTag(); + if (tag instanceof PostModel) { + postsAdapter.isSelecting = true; + toggleSelection((PostModel) tag); + } + return true; + })); + + this.lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { + if ((!autoloadPosts || isHashtag) && hasNextPage) { + main.mainBinding.swipeRefreshLayout.setRefreshing(true); + stopCurrentExecutor(); + currentlyExecuting = new PostsFetcher(isHashtag ? main.userQuery : main.profileModel.getId(), endCursor, postsFetchListener) + .setUsername(isHashtag ? null : main.profileModel.getUsername()) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + endCursor = null; + } + }); + main.mainBinding.mainPosts.addOnScrollListener(lazyLoader); + } + + private void setupFeed() { + main.mainBinding.feedStories.setLayoutManager(new LinearLayoutManager(main, LinearLayoutManager.HORIZONTAL, false)); + main.mainBinding.feedStories.setAdapter(feedStoriesAdapter); + refreshFeedStories(); + + final LinearLayoutManager layoutManager = new LinearLayoutManager(main); + main.mainBinding.feedPosts.setLayoutManager(layoutManager); + main.mainBinding.feedPosts.setAdapter(feedAdapter = new FeedAdapter(main, main.feedItems, (view, text, isHashtag) -> + new AlertDialog.Builder(main).setMessage(isHashtag ? R.string.comment_view_mention_hash_search : R.string.comment_view_mention_user_search) + .setTitle(text).setNegativeButton(R.string.cancel, null).setPositiveButton(R.string.ok, (dialog, which) -> { + if (Main.scanHack != null) { + main.mainBinding.drawerLayout.closeDrawers(); + Main.scanHack.onResult(text); + } + }).show())); + + main.mainBinding.feedSwipeRefreshLayout.setOnRefreshListener(() -> { + refreshFeedStories(); + + if (feedLazyLoader != null) feedLazyLoader.resetState(); + main.feedItems.clear(); + if (feedAdapter != null) feedAdapter.notifyDataSetChanged(); + new FeedFetcher(feedFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + }); + + main.mainBinding.feedPosts.addOnScrollListener(feedLazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { + if (feedHasNextPage) { + main.mainBinding.feedSwipeRefreshLayout.setRefreshing(true); + new FeedFetcher(feedEndCursor, feedFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + feedEndCursor = null; + } + })); + + main.mainBinding.feedPosts.addOnScrollListener(new VideoAwareRecyclerScroller(main, main.feedItems, + (itemPos, player) -> currentFeedPlayer = player)); + + new FeedFetcher(feedFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + private void refreshFeedStories() { + // todo setup feed stories + if (prevStoriesFetcher != null) { + try { + prevStoriesFetcher.cancel(true); + } catch (final Exception e) { + // ignore + } + } + prevStoriesFetcher = new FeedStoriesFetcher(feedStoriesListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + private void setupExplore() { + final GridAutofitLayoutManager layoutManager = new GridAutofitLayoutManager(main, Utils.convertDpToPx(130)); + main.mainBinding.discoverPosts.setLayoutManager(layoutManager); + main.mainBinding.discoverPosts.addItemDecoration(new GridSpacingItemDecoration(Utils.convertDpToPx(4))); + + main.mainBinding.discoverSwipeRefreshLayout.setOnRefreshListener(() -> { + if (discoverLazyLoader != null) discoverLazyLoader.resetState(); + main.discoverItems.clear(); + if (discoverAdapter != null) discoverAdapter.notifyDataSetChanged(); + new DiscoverFetcher(null, discoverFetchListener, false).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + }); + + main.mainBinding.discoverPosts.setAdapter(discoverAdapter = new DiscoverAdapter(main.discoverItems, v -> { + final Object tag = v.getTag(); + if (tag instanceof DiscoverItemModel) { + final DiscoverItemModel itemModel = (DiscoverItemModel) tag; + + if (discoverAdapter.isSelecting) toggleDiscoverSelection(itemModel); + else main.startActivity(new Intent(main, PostViewer.class) + .putExtra(Constants.EXTRAS_INDEX, itemModel.getPosition()) + .putExtra(Constants.EXTRAS_TYPE, ItemGetType.DISCOVER_ITEMS) + .putExtra(Constants.EXTRAS_POST, new PostModel(itemModel.getShortCode()))); + } + }, v -> { + final Object tag = v.getTag(); + if (tag instanceof DiscoverItemModel) { + discoverAdapter.isSelecting = true; + toggleDiscoverSelection((DiscoverItemModel) tag); + } + return true; + })); + + main.mainBinding.discoverPosts.addOnScrollListener(discoverLazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { + if (discoverHasMore) { + main.mainBinding.discoverSwipeRefreshLayout.setRefreshing(true); + new DiscoverFetcher(discoverEndMaxId, discoverFetchListener, false).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + discoverEndMaxId = null; + } + })); + + new DiscoverFetcher(null, discoverFetchListener, true).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + public void onIntent(final Intent intent) { + if (intent != null) { + final String action = intent.getAction(); + if (!Utils.isEmpty(action) && !Intent.ACTION_MAIN.equals(action)) { + intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); + + boolean error = true; + + String data = null; + final Bundle extras = intent.getExtras(); + if (extras != null) { + final Object extraData = extras.get(Intent.EXTRA_TEXT); + if (extraData != null) { + error = false; + data = extraData.toString(); + } + } + + if (error) { + final Uri intentData = intent.getData(); + if (intentData != null) data = intentData.toString(); + } + + if (data != null && !Utils.isEmpty(data)) { + if (data.indexOf('\n') > 0) data = data.substring(data.lastIndexOf('\n') + 1); + + final IntentModel model = Utils.stripString(data); + if (model != null) { + final String modelText = model.getText(); + final IntentModelType modelType = model.getType(); + + if (modelType == IntentModelType.POST) { + main.startActivityForResult(new Intent(main, PostViewer.class) + .putExtra(Constants.EXTRAS_USER, main.userQuery) + .putExtra(Constants.EXTRAS_POST, new PostModel(modelText)), 9629); + } else { + main.addToStack(); + main.userQuery = modelType == IntentModelType.HASHTAG ? '#' + modelText : modelText; + onRefresh(); + } + } + } + } + } + } + + @Override + public void onRefresh() { + main.mainBinding.drawerLayout.closeDrawers(); + if (lazyLoader != null) lazyLoader.resetState(); + stopCurrentExecutor(); + main.allItems.clear(); + main.selectedItems.clear(); + if (postsAdapter != null) { + postsAdapter.isSelecting = false; + postsAdapter.notifyDataSetChanged(); + } + main.mainBinding.appBarLayout.setExpanded(true, true); + main.mainBinding.privatePage.setVisibility(View.GONE); + main.mainBinding.mainProfileImage.setImageBitmap(null); + main.mainBinding.mainProfileImage.setImageDrawable(null); + main.mainBinding.mainUrl.setText(null); + main.mainBinding.mainFullName.setText(null); + main.mainBinding.mainPostCount.setText(null); + main.mainBinding.mainFollowers.setText(null); + main.mainBinding.mainFollowing.setText(null); + main.mainBinding.mainBiography.setText(null); + main.mainBinding.mainBiography.setEnabled(false); + main.mainBinding.mainProfileImage.setEnabled(false); + main.mainBinding.mainBiography.setMentionClickListener(null); + main.mainBinding.mainUrl.setVisibility(View.GONE); + main.mainBinding.isVerified.setVisibility(View.GONE); + + main.mainBinding.mainPosts.setNestedScrollingEnabled(false); + main.mainBinding.highlightsList.setVisibility(View.GONE); + collapsingToolbar.setVisibility(View.GONE); + main.highlightsAdapter.setData(null); + + main.mainBinding.swipeRefreshLayout.setRefreshing(main.userQuery != null); + if (main.userQuery == null) { + main.mainBinding.toolbar.toolbar.setTitle(R.string.app_name); + return; + } + + isHashtag = main.userQuery.charAt(0) == '#'; + collapsingToolbar.setVisibility(isHashtag ? View.GONE : View.VISIBLE); + + if (isHashtag) { + main.mainBinding.toolbar.toolbar.setTitle(resources.getString(R.string.title_hashtag_prefix) + main.userQuery); + main.mainBinding.infoContainer.setVisibility(View.GONE); + + currentlyExecuting = new PostsFetcher(main.userQuery, postsFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + + } else { + main.mainBinding.toolbar.toolbar.setTitle(main.userQuery); + main.mainBinding.infoContainer.setVisibility(View.VISIBLE); + + currentlyExecuting = new ProfileFetcher(main.userQuery, profileModel -> { + main.profileModel = profileModel; + + if (profileModel == null) { + main.mainBinding.swipeRefreshLayout.setRefreshing(false); + Toast.makeText(main, R.string.error_loading_profile, Toast.LENGTH_SHORT).show(); + main.mainBinding.toolbar.toolbar.setTitle(R.string.app_name); + return; + } + + main.mainBinding.isVerified.setVisibility(profileModel.isVerified() ? View.VISIBLE : View.GONE); + final String profileId = profileModel.getId(); + + final boolean isLoggedIn = !Utils.isEmpty(Utils.settingsHelper.getString(Constants.COOKIE)); + if (isLoggedIn) { + new StoryStatusFetcher(profileId, result -> { + main.storyModels = result; + if (result != null && result.length > 0) main.mainBinding.mainProfileImage.setStoriesBorder(); + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + + new HighlightsFetcher(profileId, result -> { + if (result != null && result.length > 0) { + main.mainBinding.highlightsList.setVisibility(View.VISIBLE); + main.highlightsAdapter.setData(result); + } + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + main.mainBinding.mainProfileImage.setEnabled(false); + Glide.with(main).load(profileModel.getSdProfilePic()).listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable final GlideException e, final Object model, final Target target, final boolean isFirstResource) { + main.mainBinding.mainProfileImage.setEnabled(false); + return false; + } + + @Override + public boolean onResourceReady(final Drawable resource, final Object model, final Target target, final DataSource dataSource, final boolean isFirstResource) { + main.mainBinding.mainProfileImage.setEnabled(true); + return false; + } + }).into(main.mainBinding.mainProfileImage); + + final long followersCount = profileModel.getFollowersCount(); + final long followingCount = profileModel.getFollowingCount(); + + final String postCount = String.valueOf(profileModel.getPostCount()); + + SpannableStringBuilder span = new SpannableStringBuilder(resources.getString(R.string.main_posts_count, postCount)); + span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0); + span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0); + main.mainBinding.mainPostCount.setText(span); + + final String followersCountStr = String.valueOf(followersCount); + final int followersCountStrLen = followersCountStr.length(); + span = new SpannableStringBuilder(resources.getString(R.string.main_posts_followers, followersCountStr)); + span.setSpan(new RelativeSizeSpan(1.2f), 0, followersCountStrLen, 0); + span.setSpan(new StyleSpan(Typeface.BOLD), 0, followersCountStrLen, 0); + main.mainBinding.mainFollowers.setText(span); + + final String followingCountStr = String.valueOf(followingCount); + final int followingCountStrLen = followingCountStr.length(); + span = new SpannableStringBuilder(resources.getString(R.string.main_posts_following, followingCountStr)); + span.setSpan(new RelativeSizeSpan(1.2f), 0, followingCountStrLen, 0); + span.setSpan(new StyleSpan(Typeface.BOLD), 0, followingCountStrLen, 0); + main.mainBinding.mainFollowing.setText(span); + + main.mainBinding.mainFullName.setText(profileModel.getName()); + + CharSequence biography = profileModel.getBiography(); + main.mainBinding.mainBiography.setCaptionIsExpandable(true); + main.mainBinding.mainBiography.setCaptionIsExpanded(true); + if (Utils.hasMentions(biography)) { + biography = Utils.getMentionText(biography); + main.mainBinding.mainBiography.setText(biography, TextView.BufferType.SPANNABLE); + main.mainBinding.mainBiography.setMentionClickListener(mentionClickListener); + } else { + main.mainBinding.mainBiography.setText(biography); + main.mainBinding.mainBiography.setMentionClickListener(null); + } + + final String url = profileModel.getUrl(); + if (Utils.isEmpty(url)) { + main.mainBinding.mainUrl.setVisibility(View.GONE); + } else { + main.mainBinding.mainUrl.setVisibility(View.VISIBLE); + main.mainBinding.mainUrl.setText(Utils.getSpannableUrl(url)); + } + + main.mainBinding.mainFullName.setSelected(true); + main.mainBinding.mainBiography.setEnabled(true); + + if (!profileModel.isPrivate()) { + main.mainBinding.swipeRefreshLayout.setRefreshing(true); + main.mainBinding.mainPosts.setVisibility(View.VISIBLE); + main.mainBinding.privatePage.setVisibility(View.GONE); + + if (isLoggedIn) { + final View.OnClickListener followClickListener = v -> main.startActivity(new Intent(main, FollowViewer.class) + .putExtra(Constants.EXTRAS_FOLLOWERS, v == main.mainBinding.mainFollowers) + .putExtra(Constants.EXTRAS_NAME, profileModel.getUsername()) + .putExtra(Constants.EXTRAS_ID, profileId)); + + main.mainBinding.mainFollowers.setOnClickListener(followersCount > 0 ? followClickListener : null); + main.mainBinding.mainFollowing.setOnClickListener(followingCount > 0 ? followClickListener : null); + } + + currentlyExecuting = new PostsFetcher(profileId, postsFetchListener).setUsername(profileModel.getUsername()) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else { + main.mainBinding.swipeRefreshLayout.setRefreshing(false); + main.mainBinding.privatePage.setVisibility(View.VISIBLE); + main.mainBinding.mainPosts.setVisibility(View.GONE); + } + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + } + + public static void stopCurrentExecutor() { + if (currentlyExecuting != null) { + try { + currentlyExecuting.cancel(true); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.MAIN_HELPER, "stopCurrentExecutor"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } + } + + private void toggleSelection(final PostModel postModel) { + if (postModel != null && postsAdapter != null) { + if (postModel.isSelected()) main.selectedItems.remove(postModel); + else main.selectedItems.add(postModel); + postModel.setSelected(!postModel.isSelected()); + notifyAdapter(postModel); + } + } + + private void notifyAdapter(final PostModel postModel) { + if (main.selectedItems.size() < 1) postsAdapter.isSelecting = false; + if (postModel.getPosition() < 0) postsAdapter.notifyDataSetChanged(); + else postsAdapter.notifyItemChanged(postModel.getPosition(), postModel); + + if (main.downloadAction != null) main.downloadAction.setVisible(postsAdapter.isSelecting); + } + + /////////////////////////////////////////////////// + private void toggleDiscoverSelection(final DiscoverItemModel itemModel) { + if (itemModel != null && discoverAdapter != null) { + if (itemModel.isSelected()) main.selectedDiscoverItems.remove(itemModel); + else main.selectedDiscoverItems.add(itemModel); + itemModel.setSelected(!itemModel.isSelected()); + notifyDiscoverAdapter(itemModel); + } + } + + private void notifyDiscoverAdapter(final DiscoverItemModel itemModel) { + if (main.selectedDiscoverItems.size() < 1) discoverAdapter.isSelecting = false; + if (itemModel.getPosition() < 0) discoverAdapter.notifyDataSetChanged(); + else discoverAdapter.notifyItemChanged(itemModel.getPosition(), itemModel); + + if (main.downloadAction != null) main.downloadAction.setVisible(discoverAdapter.isSelecting); + } + + public boolean isSelectionCleared() { + if (postsAdapter != null && postsAdapter.isSelecting) { + for (final PostModel postModel : main.selectedItems) postModel.setSelected(false); + main.selectedItems.clear(); + postsAdapter.isSelecting = false; + postsAdapter.notifyDataSetChanged(); + if (main.downloadAction != null) main.downloadAction.setVisible(false); + return false; + } else if (discoverAdapter != null && discoverAdapter.isSelecting) { + for (final DiscoverItemModel itemModel : main.selectedDiscoverItems) itemModel.setSelected(false); + main.selectedDiscoverItems.clear(); + discoverAdapter.isSelecting = false; + discoverAdapter.notifyDataSetChanged(); + if (main.downloadAction != null) main.downloadAction.setVisible(false); + return false; + } + return true; + } + + public void deselectSelection(final BasePostModel postModel) { + if (postModel instanceof PostModel) { + main.selectedItems.remove(postModel); + postModel.setSelected(false); + if (postsAdapter != null) notifyAdapter((PostModel) postModel); + } else if (postModel instanceof DiscoverItemModel) { + main.selectedDiscoverItems.remove(postModel); + postModel.setSelected(false); + if (discoverAdapter != null) notifyDiscoverAdapter((DiscoverItemModel) postModel); + } + } + + public void onPause() { + if (currentFeedPlayer != null) { + currentFeedPlayer.setPlayWhenReady(false); + currentFeedPlayer.getPlaybackState(); + } + } + + public void onResume() { + if (currentFeedPlayer != null) { + currentFeedPlayer.setPlayWhenReady(true); + currentFeedPlayer.getPlaybackState(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/activities/BaseLanguageActivity.java b/app/src/main/java/awais/instagrabber/activities/BaseLanguageActivity.java new file mode 100755 index 00000000..781aa5ea --- /dev/null +++ b/app/src/main/java/awais/instagrabber/activities/BaseLanguageActivity.java @@ -0,0 +1,11 @@ +package awais.instagrabber.activities; + +import androidx.appcompat.app.AppCompatActivity; + +import awais.instagrabber.utils.LocaleUtils; + +public abstract class BaseLanguageActivity extends AppCompatActivity { + protected BaseLanguageActivity() { + LocaleUtils.updateConfig(this); + } +} diff --git a/app/src/main/java/awais/instagrabber/activities/CommentsViewer.java b/app/src/main/java/awais/instagrabber/activities/CommentsViewer.java new file mode 100755 index 00000000..1c2c4438 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/activities/CommentsViewer.java @@ -0,0 +1,146 @@ +package awais.instagrabber.activities; + +import android.content.DialogInterface; +import android.content.Intent; +import android.content.res.Resources; +import android.os.AsyncTask; +import android.os.Bundle; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.style.RelativeSizeSpan; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.ArrayAdapter; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.SearchView; + +import awais.instagrabber.R; +import awais.instagrabber.adapters.CommentsAdapter; +import awais.instagrabber.asyncs.CommentsFetcher; +import awais.instagrabber.databinding.ActivityCommentsBinding; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.interfaces.MentionClickListener; +import awais.instagrabber.models.CommentModel; +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; + +public final class CommentsViewer extends AppCompatActivity { + private CommentsAdapter commentsAdapter; + private CommentModel commentModel; + + @Override + protected void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + final ActivityCommentsBinding commentsBinding = ActivityCommentsBinding.inflate(getLayoutInflater()); + setContentView(commentsBinding.getRoot()); + + final String shortCode; + final Intent intent = getIntent(); + if (intent == null || !intent.hasExtra(Constants.EXTRAS_SHORTCODE) + || Utils.isEmpty((shortCode = intent.getStringExtra(Constants.EXTRAS_SHORTCODE)))) { + Utils.errorFinish(this); + return; + } + + setSupportActionBar(commentsBinding.toolbar.toolbar); + commentsBinding.toolbar.toolbar.setTitle(R.string.title_comments); + commentsBinding.toolbar.toolbar.setSubtitle(shortCode); + + final Resources resources = getResources(); + + final ArrayAdapter commmentDialogAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, + new String[]{resources.getString(R.string.open_profile), + resources.getString(R.string.view_pfp), + resources.getString(R.string.comment_viewer_copy_user), + resources.getString(R.string.comment_viewer_copy_comment)}); + final DialogInterface.OnClickListener profileDialogListener = (dialog, which) -> { + final ProfileModel profileModel = commentModel.getProfileModel(); + + if (which == 0) { + searchUsername(profileModel.getUsername()); + } else if (which == 1) { + startActivity(new Intent(this, ProfileViewer.class).putExtra(Constants.EXTRAS_PROFILE, profileModel)); + } else if (which == 2) { + Utils.copyText(this, profileModel.getUsername()); + } else if (which == 3) { + Utils.copyText(this, commentModel.getText().toString()); + } + }; + + final View.OnClickListener clickListener = v -> { + final Object tag = v.getTag(); + if (tag instanceof CommentModel) { + commentModel = (CommentModel) tag; + + final String username = commentModel.getProfileModel().getUsername(); + final SpannableString title = new SpannableString(username + ":\n" + commentModel.getText()); + title.setSpan(new RelativeSizeSpan(1.23f), 0, username.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + + new AlertDialog.Builder(this).setTitle(title) + .setAdapter(commmentDialogAdapter, profileDialogListener) + .setNeutralButton(R.string.cancel, null) + .show(); + } + }; + + final MentionClickListener mentionClickListener = (view, text, isHashtag) -> + new AlertDialog.Builder(this).setTitle(text) + .setMessage(isHashtag ? R.string.comment_view_mention_hash_search : R.string.comment_view_mention_user_search) + .setNegativeButton(R.string.cancel, null).setPositiveButton(R.string.ok, + (dialog, which) -> searchUsername(text)).show(); + + new CommentsFetcher(shortCode, new FetchListener() { + @Override + public void doBefore() { + commentsBinding.toolbar.progressCircular.setVisibility(View.VISIBLE); + } + + @Override + public void onResult(final CommentModel[] commentModels) { + commentsBinding.toolbar.progressCircular.setVisibility(View.GONE); + + commentsAdapter = new CommentsAdapter(commentModels, true, clickListener, mentionClickListener); + + commentsBinding.rvComments.setAdapter(commentsAdapter); + } + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + private void searchUsername(final String text) { + if (Main.scanHack != null) { + Main.scanHack.onResult(text); + setResult(6969); + finish(); + } + } + + @Override + public boolean onCreateOptionsMenu(final Menu menu) { + getMenuInflater().inflate(R.menu.follow, menu); + + final MenuItem menuSearch = menu.findItem(R.id.action_search); + final SearchView searchView = (SearchView) menuSearch.getActionView(); + searchView.setQueryHint(getResources().getString(R.string.action_search)); + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(final String query) { + return false; + } + + @Override + public boolean onQueryTextChange(final String query) { + if (commentsAdapter != null) commentsAdapter.getFilter().filter(query); + return true; + } + }); + + menu.findItem(R.id.action_compare).setVisible(false); + + return true; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/activities/DirectMessages.java b/app/src/main/java/awais/instagrabber/activities/DirectMessages.java new file mode 100755 index 00000000..6449cdc8 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/activities/DirectMessages.java @@ -0,0 +1,113 @@ +package awais.instagrabber.activities; + +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Bundle; +import android.util.Log; + +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import java.util.ArrayList; +import java.util.Arrays; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.adapters.DirectMessagesAdapter; +import awais.instagrabber.asyncs.direct_messages.InboxFetcher; +import awais.instagrabber.customviews.helpers.RecyclerLazyLoader; +import awais.instagrabber.databinding.ActivityDmsBinding; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.direct_messages.InboxModel; +import awais.instagrabber.models.direct_messages.InboxThreadModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; + +public final class DirectMessages extends BaseLanguageActivity implements SwipeRefreshLayout.OnRefreshListener { + private final ArrayList inboxThreadModelList = new ArrayList<>(); + private final DirectMessagesAdapter messagesAdapter = new DirectMessagesAdapter(inboxThreadModelList, v -> { + final Object tag = v.getTag(); + if (tag instanceof InboxThreadModel) { + startActivity(new Intent(this, DirectMessagesUserInbox.class) + .putExtra(Constants.EXTRAS_THREAD_MODEL, (InboxThreadModel) tag) + ); + } + }); + private final FetchListener fetchListener = new FetchListener() { + @Override + public void doBefore() { + dmsBinding.swipeRefreshLayout.setRefreshing(true); + } + + @Override + public void onResult(final InboxModel inboxModel) { + if (inboxModel != null) { + endCursor = inboxModel.getOldestCursor(); + if ("MINCURSOR".equals(endCursor) || "MAXCURSOR".equals(endCursor)) endCursor = null; + // todo get request / unseen count from inboxModel + + final InboxThreadModel[] threads = inboxModel.getThreads(); + if (threads != null) { + final int oldSize = inboxThreadModelList.size(); + inboxThreadModelList.addAll(Arrays.asList(threads)); + + messagesAdapter.notifyItemRangeInserted(oldSize, threads.length); + } + } + + dmsBinding.swipeRefreshLayout.setRefreshing(false); + stopCurrentExecutor(); + } + }; + private String endCursor; + private RecyclerLazyLoader lazyLoader; + private AsyncTask currentlyRunning; + private ActivityDmsBinding dmsBinding; + + @Override + protected void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + dmsBinding = ActivityDmsBinding.inflate(getLayoutInflater()); + setContentView(dmsBinding.getRoot()); + + dmsBinding.swipeRefreshLayout.setOnRefreshListener(this); + + final LinearLayoutManager layoutManager = new LinearLayoutManager(this); + dmsBinding.rvDirectMessages.setLayoutManager(layoutManager); + dmsBinding.rvDirectMessages.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL)); + dmsBinding.rvDirectMessages.setAdapter(messagesAdapter); + + lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { + if (!Utils.isEmpty(endCursor)) + currentlyRunning = new InboxFetcher(endCursor, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + endCursor = null; + }); + + dmsBinding.rvDirectMessages.addOnScrollListener(lazyLoader); + + stopCurrentExecutor(); + currentlyRunning = new InboxFetcher(null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + @Override + public void onRefresh() { + endCursor = null; + lazyLoader.resetState(); + inboxThreadModelList.clear(); + messagesAdapter.notifyDataSetChanged(); + + stopCurrentExecutor(); + currentlyRunning = new InboxFetcher(null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + private void stopCurrentExecutor() { + if (currentlyRunning != null) { + try { + currentlyRunning.cancel(true); + } catch (final Exception e) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/activities/DirectMessagesUserInbox.java b/app/src/main/java/awais/instagrabber/activities/DirectMessagesUserInbox.java new file mode 100755 index 00000000..e8b077d5 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/activities/DirectMessagesUserInbox.java @@ -0,0 +1,101 @@ +package awais.instagrabber.activities; + +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Bundle; +import android.util.Log; +import android.widget.Toast; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import awais.instagrabber.R; +import awais.instagrabber.adapters.MessageItemsAdapter; +import awais.instagrabber.asyncs.direct_messages.UserInboxFetcher; +import awais.instagrabber.customviews.helpers.RecyclerLazyLoader; +import awais.instagrabber.databinding.ActivityDmsBinding; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.models.direct_messages.DirectItemModel; +import awais.instagrabber.models.direct_messages.InboxThreadModel; +import awais.instagrabber.models.enums.UserInboxDirection; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; + +public final class DirectMessagesUserInbox extends AppCompatActivity { + private final ArrayList users = new ArrayList<>(); + private final ArrayList directItemModels = new ArrayList<>(); + private final FetchListener fetchListener = new FetchListener() { + @Override + public void doBefore() { + dmsBinding.swipeRefreshLayout.setRefreshing(true); + } + + @Override + public void onResult(final InboxThreadModel result) { + if (result == null && "MINCURSOR".equals(endCursor) || "MAXCURSOR".equals(endCursor) || Utils.isEmpty(endCursor)) + Toast.makeText(DirectMessagesUserInbox.this, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); + + if (result != null) { + endCursor = result.getPrevCursor(); + if ("MINCURSOR".equals(endCursor) || "MAXCURSOR".equals(endCursor)) endCursor = null; + + users.clear(); + users.addAll(Arrays.asList(result.getUsers())); + + final int oldSize = directItemModels.size(); + final List itemModels = Arrays.asList(result.getItems()); + directItemModels.addAll(itemModels); + messageItemsAdapter.notifyItemRangeInserted(oldSize, itemModels.size()); + } + + dmsBinding.swipeRefreshLayout.setRefreshing(false); + } + }; + private String endCursor; + private ActivityDmsBinding dmsBinding; + private MessageItemsAdapter messageItemsAdapter; + + @Override + protected void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + dmsBinding = ActivityDmsBinding.inflate(getLayoutInflater()); + setContentView(dmsBinding.getRoot()); + + final InboxThreadModel threadModel; + final Intent intent = getIntent(); + if (intent == null || !intent.hasExtra(Constants.EXTRAS_THREAD_MODEL) || + (threadModel = (InboxThreadModel) intent.getSerializableExtra(Constants.EXTRAS_THREAD_MODEL)) == null) { + Utils.errorFinish(this); + return; + } + + dmsBinding.swipeRefreshLayout.setEnabled(false); + + final LinearLayoutManager layoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, true); + dmsBinding.rvDirectMessages.setLayoutManager(layoutManager); + + dmsBinding.rvDirectMessages.addOnScrollListener(new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { + if (!Utils.isEmpty(endCursor)) { + new UserInboxFetcher(threadModel.getThreadId(), UserInboxDirection.OLDER, + endCursor, fetchListener).execute(); // serial because we don't want messages to be randomly ordered + } + })); + + dmsBinding.rvDirectMessages.setAdapter(messageItemsAdapter = new MessageItemsAdapter(directItemModels, users, v -> { + // todo do something with clicked message + Log.d("AWAISKING_APP", "--> " + v.getTag()); + }, (view, text, isHashtag) -> { + // todo mention click stuff + + })); + + new UserInboxFetcher(threadModel.getThreadId(), UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/activities/FollowViewer.java b/app/src/main/java/awais/instagrabber/activities/FollowViewer.java new file mode 100755 index 00000000..e1dceacb --- /dev/null +++ b/app/src/main/java/awais/instagrabber/activities/FollowViewer.java @@ -0,0 +1,348 @@ +package awais.instagrabber.activities; + +import android.content.Intent; +import android.content.res.Resources; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.ArrayAdapter; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.SearchView; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import java.util.ArrayList; +import java.util.Arrays; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.R; +import awais.instagrabber.adapters.FollowAdapter; +import awais.instagrabber.asyncs.FollowFetcher; +import awais.instagrabber.databinding.ActivityFollowBinding; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.FollowModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; +import awaisomereport.LogCollector; +import thoughtbot.expandableadapter.ExpandableGroup; + +import static awais.instagrabber.utils.Utils.logCollector; + +public final class FollowViewer extends BaseLanguageActivity implements SwipeRefreshLayout.OnRefreshListener { + private final ArrayList followModels = new ArrayList<>(); + private final ArrayList followingModels = new ArrayList<>(); + private final ArrayList followersModels = new ArrayList<>(); + private final ArrayList allFollowing = new ArrayList<>(); + private boolean followers, isCompare = false; + private String id, name, namePost, type; + private Resources resources; + private FollowModel model; + private FollowAdapter adapter; + private View.OnClickListener clickListener; + private ActivityFollowBinding followBinding; + private AsyncTask currentlyExecuting; + + @Override + protected void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + followBinding = ActivityFollowBinding.inflate(getLayoutInflater()); + setContentView(followBinding.getRoot()); + + final Intent intent = getIntent(); + if (intent == null || Utils.isEmpty(id = intent.getStringExtra(Constants.EXTRAS_ID))) { + Utils.errorFinish(this); + return; + } + + setSupportActionBar(followBinding.toolbar.toolbar); + + followers = intent.getBooleanExtra(Constants.EXTRAS_FOLLOWERS, false); + name = intent.getStringExtra(Constants.EXTRAS_NAME); + namePost = name + " is"; + if (Utils.isEmpty(name)) { + name = "You"; + namePost = "You're"; + } + + followBinding.toolbar.toolbar.setTitle(name); + + resources = getResources(); + final ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new String[]{ + resources.getString(R.string.open_profile), resources.getString(R.string.followers_open_in_insta)}); + final AlertDialog alertDialog = new AlertDialog.Builder(this).setAdapter(adapter, (dialog, which) -> { + if (model != null) { + if (which == 0) { + if (Main.scanHack != null) { + Main.scanHack.onResult(model.getUsername()); + finish(); + } + } else { + final Intent actIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://instagram.com/" + model.getUsername())); + if (Utils.isInstagramInstalled) actIntent.setPackage("com.instagram.android"); + startActivity(actIntent); + } + } + }).setTitle(R.string.what_to_do_dialog).create(); + + clickListener = v -> { + final Object tag = v.getTag(); + if (tag instanceof FollowModel) { + model = (FollowModel) tag; + if (!alertDialog.isShowing()) alertDialog.show(); + } + }; + + followBinding.swipeRefreshLayout.setOnRefreshListener(this); + + onRefresh(); + } + + @Override + public void onRefresh() { + if (isCompare) listCompare(); + else listFollows(); + } + + private void listFollows() { + stopCurrentExecutor(); + + type = resources.getString(followers ? R.string.followers_type_followers : R.string.followers_type_following); + followBinding.toolbar.toolbar.setSubtitle(type); + + followModels.clear(); + + final FetchListener fetchListener = new FetchListener() { + @Override + public void doBefore() { + followBinding.swipeRefreshLayout.setRefreshing(true); + } + + @Override + public void onResult(final FollowModel[] result) { + if (result == null) followBinding.swipeRefreshLayout.setRefreshing(false); + else { + followModels.addAll(Arrays.asList(result)); + + final FollowModel model = result[result.length - 1]; + if (model != null && model.hasNextPage()) { + stopCurrentExecutor(); + currentlyExecuting = new FollowFetcher(id, followers, model.getEndCursor(), this) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + model.setPageCursor(false, null); + } else { + followBinding.swipeRefreshLayout.setRefreshing(false); + + refreshAdapter(followModels, null, null, null); + } + } + } + }; + + currentlyExecuting = new FollowFetcher(id, followers, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + private void listCompare() { + stopCurrentExecutor(); + + followBinding.toolbar.toolbar.setSubtitle(R.string.followers_compare); + + allFollowing.clear(); + followersModels.clear(); + followingModels.clear(); + + final FetchListener followingFetchListener = new FetchListener() { + @Override + public void onResult(final FollowModel[] result) { + if (result != null) { + followingModels.addAll(Arrays.asList(result)); + + final FollowModel model = result[result.length - 1]; + if (model != null && model.hasNextPage()) { + stopCurrentExecutor(); + currentlyExecuting = new FollowFetcher(id, false, model.getEndCursor(), this) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + model.setPageCursor(false, null); + } else { + allFollowing.addAll(followersModels); + allFollowing.retainAll(followingModels); + + for (final FollowModel followModel : allFollowing) { + followersModels.remove(followModel); + followingModels.remove(followModel); + } + + allFollowing.trimToSize(); + followersModels.trimToSize(); + followingModels.trimToSize(); + + followBinding.swipeRefreshLayout.setRefreshing(false); + + refreshAdapter(null, followingModels, followersModels, allFollowing); + } + } else followBinding.swipeRefreshLayout.setRefreshing(false); + } + }; + final FetchListener followersFetchListener = new FetchListener() { + @Override + public void doBefore() { + followBinding.swipeRefreshLayout.setRefreshing(true); + } + + @Override + public void onResult(final FollowModel[] result) { + if (result != null) { + followersModels.addAll(Arrays.asList(result)); + final FollowModel model = result[result.length - 1]; + if (model == null || !model.hasNextPage()) { + stopCurrentExecutor(); + currentlyExecuting = new FollowFetcher(id, false, followingFetchListener) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else { + stopCurrentExecutor(); + currentlyExecuting = new FollowFetcher(id, true, model.getEndCursor(), this) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + model.setPageCursor(false, null); + } + } + } + }; + + currentlyExecuting = new FollowFetcher(id, true, followersFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + @Override + public boolean onCreateOptionsMenu(final Menu menu) { + getMenuInflater().inflate(R.menu.follow, menu); + + final MenuItem menuSearch = menu.findItem(R.id.action_search); + + final SearchView searchView = (SearchView) menuSearch.getActionView(); + searchView.setQueryHint(getResources().getString(R.string.action_search)); + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { +// private final Filter filter = new Filter() { +// private final ArrayList searchFollowModels = new ArrayList<>(followModels.size() / 2); +// private final ArrayList searchFollowingModels = new ArrayList<>(followingModels.size() / 2); +// private final ArrayList searchFollowersModels = new ArrayList<>(followersModels.size() / 2); +// private final ArrayList searchAllFollowing = new ArrayList<>(allFollowing.size() / 2); +// +// @Nullable +// @Override +// protected FilterResults performFiltering(@NonNull final CharSequence constraint) { +// searchFollowModels.clear(); +// searchFollowingModels.clear(); +// searchFollowersModels.clear(); +// searchAllFollowing.clear(); +// +// final int followModelsSize = followModels.size(); +// final int followingModelsSize = followingModels.size(); +// final int followersModelsSize = followersModels.size(); +// final int allFollowingSize = allFollowing.size(); +// +// int maxSize = followModelsSize; +// if (maxSize < followingModelsSize) maxSize = followingModelsSize; +// if (maxSize < followersModelsSize) maxSize = followersModelsSize; +// if (maxSize < allFollowingSize) maxSize = allFollowingSize; +// +// final String query = constraint.toString().toLowerCase(); +// FollowModel followModel; +// while (maxSize != -1) { +// if (maxSize < followModelsSize) { +// followModel = followModels.get(maxSize); +// if (Utils.hasKey(query, followModel.getUsername(), followModel.getFullName())) +// searchFollowModels.add(followModel); +// } +// +// if (maxSize < followingModelsSize) { +// followModel = followingModels.get(maxSize); +// if (Utils.hasKey(query, followModel.getUsername(), followModel.getFullName())) +// searchFollowingModels.add(followModel); +// } +// +// if (maxSize < followersModelsSize) { +// followModel = followersModels.get(maxSize); +// if (Utils.hasKey(query, followModel.getUsername(), followModel.getFullName())) +// searchFollowersModels.add(followModel); +// } +// +// if (maxSize < allFollowingSize) { +// followModel = allFollowing.get(maxSize); +// if (Utils.hasKey(query, followModel.getUsername(), followModel.getFullName())) +// searchAllFollowing.add(followModel); +// } +// +// --maxSize; +// } +// +// return null; +// } +// +// @Override +// protected void publishResults(final CharSequence query, final FilterResults results) { +// refreshAdapter(searchFollowModels, searchFollowingModels, searchFollowersModels, searchAllFollowing); +// } +// }; + + @Override + public boolean onQueryTextSubmit(final String query) { + return false; + } + + @Override + public boolean onQueryTextChange(final String query) { +// if (Utils.isEmpty(query)) refreshAdapter(followModels, followingModels, followersModels, allFollowing); +// else filter.filter(query.toLowerCase()); + if (adapter != null) adapter.getFilter().filter(query); + return true; + } + }); + + final MenuItem menuCompare = menu.findItem(R.id.action_compare); + menuCompare.setOnMenuItemClickListener(item -> { + followBinding.rvFollow.setAdapter(null); + if (isCompare) listFollows(); + else listCompare(); + isCompare = !isCompare; + return true; + }); + + return true; + } + + private void refreshAdapter(final ArrayList followModels, final ArrayList followingModels, + final ArrayList followersModels, final ArrayList allFollowing) { + final ArrayList groups = new ArrayList<>(1); + + if (isCompare) { + if (followingModels.size() > 0) + groups.add(new ExpandableGroup(resources.getString(R.string.followers_not_following, name), followingModels)); + if (followersModels.size() > 0) + groups.add(new ExpandableGroup(resources.getString(R.string.followers_not_follower, namePost), followersModels)); + if (allFollowing.size() > 0) + groups.add(new ExpandableGroup(resources.getString(R.string.followers_both_following), allFollowing)); + } else { + final ExpandableGroup group = new ExpandableGroup(type, followModels); + groups.add(group); + } + + adapter = new FollowAdapter(this, clickListener, groups); + adapter.toggleGroup(0); + followBinding.rvFollow.setAdapter(adapter); + } + + public void stopCurrentExecutor() { + if (currentlyExecuting != null) { + try { + currentlyExecuting.cancel(true); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.MAIN_HELPER, "stopCurrentExecutor"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/activities/Login.java b/app/src/main/java/awais/instagrabber/activities/Login.java new file mode 100755 index 00000000..db825719 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/activities/Login.java @@ -0,0 +1,130 @@ +package awais.instagrabber.activities; + +import android.annotation.SuppressLint; +import android.graphics.Bitmap; +import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.webkit.WebChromeClient; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.CompoundButton; +import android.widget.Toast; + +import androidx.annotation.Nullable; + +import awais.instagrabber.R; +import awais.instagrabber.databinding.ActivityLoginBinding; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; + +import static awais.instagrabber.utils.Utils.settingsHelper; + +public final class Login extends BaseLanguageActivity implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { + private final WebViewClient webViewClient = new WebViewClient() { + @Override + public void onPageStarted(final WebView view, final String url, final Bitmap favicon) { + webViewUrl = url; + } + + @Override + public void onPageFinished(final WebView view, final String url) { + webViewUrl = url; + } + }; + private final WebChromeClient webChromeClient = new WebChromeClient(); + private String webViewUrl, defaultUserAgent; + private ActivityLoginBinding loginBinding; + + @Override + protected void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + loginBinding = ActivityLoginBinding.inflate(getLayoutInflater()); + setContentView(loginBinding.getRoot()); + + initWebView(); + + loginBinding.desktopMode.setOnCheckedChangeListener(this); + loginBinding.cookies.setOnClickListener(this); + loginBinding.refresh.setOnClickListener(this); + } + + @Override + public void onClick(final View v) { + if (v == loginBinding.refresh) { + loginBinding.webView.loadUrl("https://instagram.com/"); + } else if (v == loginBinding.cookies) { + final String mainCookie = Utils.getCookie(webViewUrl); + if (Utils.isEmpty(mainCookie)) + Toast.makeText(this, R.string.login_error_loading_cookies, Toast.LENGTH_SHORT).show(); + else { + Utils.setupCookies(mainCookie); + settingsHelper.putString(Constants.COOKIE, mainCookie); + Toast.makeText(this, R.string.login_success_loading_cookies, Toast.LENGTH_SHORT).show(); + finish(); + } + } + } + + @Override + public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) { + final WebSettings webSettings = loginBinding.webView.getSettings(); + + final String newUserAgent = isChecked ? "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36" + : defaultUserAgent; + + webSettings.setUserAgentString(newUserAgent); + webSettings.setUseWideViewPort(isChecked); + webSettings.setLoadWithOverviewMode(isChecked); + webSettings.setSupportZoom(isChecked); + webSettings.setBuiltInZoomControls(isChecked); + + loginBinding.webView.loadUrl("https://instagram.com/"); + } + + @SuppressLint("SetJavaScriptEnabled") + private void initWebView() { + if (loginBinding != null) { + loginBinding.webView.setWebChromeClient(webChromeClient); + loginBinding.webView.setWebViewClient(webViewClient); + final WebSettings webSettings = loginBinding.webView.getSettings(); + if (webSettings != null) { + if (defaultUserAgent == null) defaultUserAgent = webSettings.getUserAgentString(); + webSettings.setJavaScriptEnabled(true); + webSettings.setDomStorageEnabled(true); + webSettings.setSupportZoom(true); + webSettings.setBuiltInZoomControls(true); + webSettings.setDisplayZoomControls(false); + webSettings.setLoadWithOverviewMode(true); + webSettings.setUseWideViewPort(true); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + webSettings.setAllowFileAccessFromFileURLs(true); + webSettings.setAllowUniversalAccessFromFileURLs(true); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) + webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); + } + + loginBinding.webView.loadUrl("https://instagram.com/"); + } + } + + @Override + protected void onPause() { + if (loginBinding != null) loginBinding.webView.onPause(); + super.onPause(); + } + + @Override + protected void onResume() { + super.onResume(); + if (loginBinding != null) loginBinding.webView.onResume(); + } + + @Override + protected void onDestroy() { + if (loginBinding != null) loginBinding.webView.destroy(); + super.onDestroy(); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/activities/Main.java b/app/src/main/java/awais/instagrabber/activities/Main.java new file mode 100755 index 00000000..188abc6d --- /dev/null +++ b/app/src/main/java/awais/instagrabber/activities/Main.java @@ -0,0 +1,480 @@ +package awais.instagrabber.activities; + +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.database.MatrixCursor; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.PersistableBundle; +import android.provider.BaseColumns; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.SearchView; +import androidx.fragment.app.FragmentManager; +import androidx.recyclerview.widget.GridLayoutManager; + +import java.util.ArrayList; +import java.util.Stack; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.MainHelper; +import awais.instagrabber.R; +import awais.instagrabber.adapters.HighlightsAdapter; +import awais.instagrabber.adapters.SuggestionsAdapter; +import awais.instagrabber.asyncs.SuggestionsFetcher; +import awais.instagrabber.asyncs.UsernameFetcher; +import awais.instagrabber.customviews.MouseDrawer; +import awais.instagrabber.databinding.ActivityMainBinding; +import awais.instagrabber.dialogs.AboutDialog; +import awais.instagrabber.dialogs.QuickAccessDialog; +import awais.instagrabber.dialogs.SettingsDialog; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.interfaces.ItemGetter; +import awais.instagrabber.models.DiscoverItemModel; +import awais.instagrabber.models.FeedModel; +import awais.instagrabber.models.HighlightModel; +import awais.instagrabber.models.PostModel; +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.models.StoryModel; +import awais.instagrabber.models.SuggestionModel; +import awais.instagrabber.models.enums.DownloadMethod; +import awais.instagrabber.models.enums.ItemGetType; +import awais.instagrabber.models.enums.SuggestionType; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.DataBox; +import awais.instagrabber.utils.FlavorTown; +import awais.instagrabber.utils.MyApps; +import awais.instagrabber.utils.Utils; + +import static awais.instagrabber.utils.Utils.settingsHelper; + +public final class Main extends BaseLanguageActivity { + public static FetchListener scanHack; + public static ItemGetter itemGetter; + // -------- items -------- + public final ArrayList allItems = new ArrayList<>(); + public final ArrayList feedItems = new ArrayList<>(); + public final ArrayList discoverItems = new ArrayList<>(); + // -------- items -------- + public final ArrayList selectedItems = new ArrayList<>(); + public final ArrayList selectedDiscoverItems = new ArrayList<>(); + // -------- items -------- + public final HighlightsAdapter highlightsAdapter = new HighlightsAdapter(null, new View.OnClickListener() { + @Override + public void onClick(final View v) { + final Object tag = v.getTag(); + if (tag instanceof HighlightModel) { + final HighlightModel highlightModel = (HighlightModel) tag; + startActivity(new Intent(Main.this, StoryViewer.class) + .putExtra(Constants.EXTRAS_USERNAME, userQuery) + .putExtra(Constants.EXTRAS_HIGHLIGHT, highlightModel.getTitle()) + .putExtra(Constants.EXTRAS_STORIES, highlightModel.getStoryModels())); + } + } + }); + private SuggestionsAdapter suggestionAdapter; + private MenuItem searchAction; + public ActivityMainBinding mainBinding; + public SearchView searchView; + public MenuItem downloadAction, settingsAction, dmsAction; + public StoryModel[] storyModels; + public String userQuery = null; + public MainHelper mainHelper; + public ProfileModel profileModel; + private AutoCompleteTextView searchAutoComplete; + private ArrayAdapter profileDialogAdapter; + private DialogInterface.OnClickListener profileDialogListener; + private Stack queriesStack; + + public Main() { + super(); + Utils.changeTheme(); + } + + @Override + protected void onCreate(@Nullable final Bundle bundle) { + super.onCreate(bundle); + mainBinding = ActivityMainBinding.inflate(getLayoutInflater()); + setContentView(mainBinding.getRoot()); + + FlavorTown.updateCheck(this); + FlavorTown.changelogCheck(this); + + final String cookie = settingsHelper.getString(Constants.COOKIE); + final String uid = Utils.getUserIdFromCookie(cookie); + Utils.setupCookies(cookie); + + MainHelper.stopCurrentExecutor(); + mainHelper = new MainHelper(this); + if (bundle == null) { + queriesStack = new Stack<>(); + userQuery = null; + } else { + setStack(bundle); + userQuery = bundle.getString("query"); + } + + itemGetter = itemGetType -> { + if (itemGetType == ItemGetType.MAIN_ITEMS) return allItems; + if (itemGetType == ItemGetType.DISCOVER_ITEMS) return discoverItems; + if (itemGetType == ItemGetType.FEED_ITEMS) return feedItems; + return null; + }; + + scanHack = result -> { + if (mainHelper != null && !Utils.isEmpty(result)) { + closeAnyOpenDrawer(); + addToStack(); + userQuery = result; + mainHelper.onRefresh(); + } + }; + + // searches for your userid and returns username + if (uid != null) { + final FetchListener fetchListener = username -> { + if (!Utils.isEmpty(username)) { + if (!BuildConfig.DEBUG) { + userQuery = username; + if (mainHelper != null && !mainBinding.swipeRefreshLayout.isRefreshing()) mainHelper.onRefresh(); + } + // adds cookies to database for quick access + final DataBox.CookieModel cookieModel = Utils.dataBox.getCookie(uid); + if (Utils.dataBox.getCookieCount() == 0 || cookieModel == null || Utils.isEmpty(cookieModel.getUsername())) + Utils.dataBox.addUserCookie(new DataBox.CookieModel(uid, username, cookie)); + } + }; + boolean found = false; + final DataBox.CookieModel cookieModel = Utils.dataBox.getCookie(uid); + if (cookieModel != null) { + final String username = cookieModel.getUsername(); + if (username != null) { + found = true; + fetchListener.onResult(username); + } + } + + if (!found) // if not in database, fetch info from instagram + new UsernameFetcher(uid, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + suggestionAdapter = new SuggestionsAdapter(this, v -> { + final Object tag = v.getTag(); + if (tag instanceof CharSequence) { + addToStack(); + userQuery = tag.toString(); + mainHelper.onRefresh(); + } + if (searchView != null && !searchView.isIconified()) { + if (searchAction != null) searchAction.collapseActionView(); + searchView.setIconified(true); + searchView.setIconified(true); + } + }); + + final Resources resources = getResources(); + profileDialogAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, + new String[]{resources.getString(R.string.view_pfp), resources.getString(R.string.show_stories)}); + profileDialogListener = (dialog, which) -> { + final Intent intent; + if (which == 0 || storyModels == null || storyModels.length < 1) + intent = new Intent(this, ProfileViewer.class).putExtra(Constants.EXTRAS_PROFILE, profileModel); + else intent = new Intent(this, StoryViewer.class).putExtra(Constants.EXTRAS_USERNAME, userQuery) + .putExtra(Constants.EXTRAS_STORIES, storyModels); + startActivity(intent); + }; + + final View.OnClickListener onClickListener = v -> { + if (v == mainBinding.mainBiography) { + Utils.copyText(this, mainBinding.mainBiography.getText().toString()); + } else if (v == mainBinding.mainProfileImage) { + if (storyModels == null || storyModels.length <= 0) { + profileDialogListener.onClick(null, 0); + } else { + // because sometimes configuration changes made this crash on some phones + new AlertDialog.Builder(this).setAdapter(profileDialogAdapter, profileDialogListener) + .setNeutralButton(R.string.cancel, null).show(); + } + } + }; + + mainBinding.mainBiography.setOnClickListener(onClickListener); + mainBinding.mainProfileImage.setOnClickListener(onClickListener); + + mainBinding.mainBiography.setEnabled(false); + mainBinding.mainProfileImage.setEnabled(false); + + final boolean isQueryNull = userQuery == null; + if (isQueryNull) allItems.clear(); + if (BuildConfig.DEBUG && isQueryNull) userQuery = "the.badak"; // todo + if (!mainBinding.swipeRefreshLayout.isRefreshing() && userQuery != null) mainHelper.onRefresh(); + + mainHelper.onIntent(getIntent()); + } + + private void downloadSelectedItems() { + if (selectedItems.size() > 0) { + Utils.batchDownload(this, userQuery, DownloadMethod.DOWNLOAD_MAIN, selectedItems); + } else if (selectedDiscoverItems.size() > 0) { + Utils.batchDownload(this, null, DownloadMethod.DOWNLOAD_DISCOVER, selectedDiscoverItems); + } + } + + @Override + protected void onNewIntent(final Intent intent) { + super.onNewIntent(intent); + mainHelper.onIntent(intent); + } + + @Override + public void onSaveInstanceState(@NonNull final Bundle outState, @NonNull final PersistableBundle outPersistentState) { + outState.putString("query", userQuery); + outState.putSerializable("stack", queriesStack); + super.onSaveInstanceState(outState, outPersistentState); + } + + @Override + public void onRestoreInstanceState(@Nullable final Bundle savedInstanceState, @Nullable final PersistableBundle persistentState) { + super.onRestoreInstanceState(savedInstanceState, persistentState); + if (savedInstanceState != null) { + userQuery = savedInstanceState.getString("query"); + setStack(savedInstanceState); + } + } + + @Override + protected void onSaveInstanceState(@NonNull final Bundle outState) { + outState.putString("query", userQuery); + outState.putSerializable("stack", queriesStack); + super.onSaveInstanceState(outState); + } + + @Override + protected void onRestoreInstanceState(@NonNull final Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + userQuery = savedInstanceState.getString("query"); + setStack(savedInstanceState); + } + + @Override + public boolean onCreateOptionsMenu(final Menu menu) { + getMenuInflater().inflate(R.menu.menu, menu); + + final FragmentManager fragmentManager = getSupportFragmentManager(); + final MenuItem quickAccessAction = menu.findItem(R.id.action_quickaccess).setVisible(true); + + final MenuItem.OnMenuItemClickListener clickListener = item -> { + if (item == downloadAction) { + downloadSelectedItems(); + } else if (item == dmsAction) + startActivity(new Intent(this, DirectMessages.class)); + else if (item == settingsAction) + new SettingsDialog().show(fragmentManager, "settings"); + else if (item == quickAccessAction) + new QuickAccessDialog().setQuery(userQuery).show(fragmentManager, "quickAccess"); + else + new AboutDialog().show(fragmentManager, "about"); + return true; + }; + + quickAccessAction.setOnMenuItemClickListener(clickListener); + menu.findItem(R.id.action_about).setVisible(true).setOnMenuItemClickListener(clickListener); + dmsAction = menu.findItem(R.id.action_dms).setOnMenuItemClickListener(clickListener); + settingsAction = menu.findItem(R.id.action_settings).setVisible(true).setOnMenuItemClickListener(clickListener); + downloadAction = menu.findItem(R.id.action_download).setOnMenuItemClickListener(clickListener); + + if (!Utils.isEmpty(Utils.settingsHelper.getString(Constants.COOKIE))) { + settingsAction.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + dmsAction.setVisible(true).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); + } + + searchAction = menu.findItem(R.id.action_search); + searchView = (SearchView) searchAction.getActionView(); + final View searchText = searchView.findViewById(R.id.search_src_text); + if (searchText instanceof AutoCompleteTextView) + searchAutoComplete = (AutoCompleteTextView) searchText; + + searchView.setQueryHint(getResources().getString(R.string.action_search)); + searchView.setSuggestionsAdapter(suggestionAdapter); + searchView.setOnSearchClickListener(v -> searchView.setQuery(userQuery, false)); + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + private boolean searchUser, searchHash; + private AsyncTask prevSuggestionAsync; + private final String[] COLUMNS = {BaseColumns._ID, Constants.EXTRAS_USERNAME, Constants.EXTRAS_NAME, + Constants.EXTRAS_TYPE, "pfp", "verified"}; + private final FetchListener fetchListener = new FetchListener() { + @Override + public void doBefore() { + suggestionAdapter.changeCursor(null); + } + + @Override + public void onResult(final SuggestionModel[] result) { + final MatrixCursor cursor; + if (result == null) cursor = null; + else { + cursor = new MatrixCursor(COLUMNS, 0); + for (int i = 0; i < result.length; i++) { + final SuggestionModel suggestionModel = result[i]; + if (suggestionModel != null) { + final SuggestionType suggestionType = suggestionModel.getSuggestionType(); + final Object[] objects = {i, suggestionModel.getUsername(), suggestionModel.getName(), + suggestionType, suggestionModel.getProfilePic(), suggestionModel.isVerified()}; + + if (!searchHash && !searchUser) cursor.addRow(objects); + else { + final boolean isCurrHash = suggestionType == SuggestionType.TYPE_HASHTAG; + if (searchHash && isCurrHash || !searchHash && !isCurrHash) + cursor.addRow(objects); + } + } + } + } + suggestionAdapter.changeCursor(cursor); + } + }; + + private void cancelSuggestionsAsync() { + if (prevSuggestionAsync != null) + try { prevSuggestionAsync.cancel(true); } catch (final Exception ignored) { } + } + + @Override + public boolean onQueryTextSubmit(final String query) { + cancelSuggestionsAsync(); + + closeAnyOpenDrawer(); + addToStack(); + userQuery = query; + searchAction.collapseActionView(); + searchView.setIconified(true); + searchView.setIconified(true); + mainHelper.onRefresh(); + return false; + } + + @Override + public boolean onQueryTextChange(final String newText) { + cancelSuggestionsAsync(); + + if (!Utils.isEmpty(newText)) { + searchUser = newText.charAt(0) == '@'; + searchHash = newText.charAt(0) == '#'; + + if (newText.length() == 1 && (searchHash || searchUser)) { + if (searchAutoComplete != null) searchAutoComplete.setThreshold(2); + } else { + if (searchAutoComplete != null) searchAutoComplete.setThreshold(1); + prevSuggestionAsync = new SuggestionsFetcher(fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, + searchUser || searchHash ? newText.substring(1) : newText); + } + } + return true; + } + }); + + return true; + } + + @Override + public void onBackPressed() { + if (closeAnyOpenDrawer()) return; + + if (searchView != null && !searchView.isIconified()) { + if (searchAction != null) searchAction.collapseActionView(); + searchView.setIconified(true); + searchView.setIconified(true); + return; + } + + if (!mainHelper.isSelectionCleared()) return; + + final GridLayoutManager layoutManager = (GridLayoutManager) mainBinding.mainPosts.getLayoutManager(); + if (layoutManager != null && layoutManager.findFirstCompletelyVisibleItemPosition() >= layoutManager.getSpanCount()) { + mainBinding.mainPosts.smoothScrollToPosition(0); + mainBinding.appBarLayout.setExpanded(true, true); + return; + } + + if (queriesStack != null && queriesStack.size() > 0) { + userQuery = queriesStack.pop(); + if (userQuery != null) { + mainHelper.onRefresh(); + return; + } + } + + MyApps.showAlertDialog(this, (parent, view, position, id) -> { + if (id == -1 && position == -1 && parent == null) super.onBackPressed(); + else MyApps.openAppStore(this, position); + }); + } + + @Override + public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == 8020 && grantResults[0] == PackageManager.PERMISSION_GRANTED) + downloadSelectedItems(); + } + + @Override + protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 9629 && (resultCode == 1692 || resultCode == RESULT_CANCELED)) + finish(); + else if (requestCode == 6007) + Utils.showImportExportDialog(this); + else if (requestCode == 6969 && mainHelper.currentFeedPlayer != null) + mainHelper.currentFeedPlayer.setPlayWhenReady(true); + } + + @Override + protected void onPause() { + if (mainHelper != null) mainHelper.onPause(); + super.onPause(); + } + + @Override + protected void onResume() { + if (mainHelper != null) mainHelper.onResume(); + super.onResume(); + } + + private void setStack(final Bundle bundle) { + final Object stack = bundle != null ? bundle.get("stack") : null; + if (stack instanceof Stack) //noinspection unchecked + queriesStack = (Stack) stack; + } + + public void addToStack() { + if (userQuery != null) { + if (queriesStack == null) queriesStack = new Stack<>(); + queriesStack.add(userQuery); + } + } + + private boolean closeAnyOpenDrawer() { + final int childCount = mainBinding.drawerLayout.getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = mainBinding.drawerLayout.getChildAt(i); + final MouseDrawer.LayoutParams childLp = (MouseDrawer.LayoutParams) child.getLayoutParams(); + + if ((childLp.openState & MouseDrawer.LayoutParams.FLAG_IS_OPENED) == 1 || + (childLp.openState & MouseDrawer.LayoutParams.FLAG_IS_OPENING) == 2 || + childLp.onScreen >= 0.6 || childLp.isPeeking) { + mainBinding.drawerLayout.closeDrawer(child); + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/activities/PostViewer.java b/app/src/main/java/awais/instagrabber/activities/PostViewer.java new file mode 100755 index 00000000..21254a79 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/activities/PostViewer.java @@ -0,0 +1,639 @@ +package awais.instagrabber.activities; + +import android.annotation.SuppressLint; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.text.SpannableString; +import android.text.method.LinkMovementMethod; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.core.view.GestureDetectorCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.source.MediaSourceEventListener; +import com.google.android.exoplayer2.source.ProgressiveMediaSource; +import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import awais.instagrabber.R; +import awais.instagrabber.adapters.PostsMediaAdapter; +import awais.instagrabber.asyncs.PostFetcher; +import awais.instagrabber.asyncs.ProfileFetcher; +import awais.instagrabber.customviews.CommentMentionClickSpan; +import awais.instagrabber.customviews.helpers.SwipeGestureListener; +import awais.instagrabber.databinding.ActivityViewerBinding; +import awais.instagrabber.interfaces.SwipeEvent; +import awais.instagrabber.models.BasePostModel; +import awais.instagrabber.models.PostModel; +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.models.ViewerPostModel; +import awais.instagrabber.models.enums.DownloadMethod; +import awais.instagrabber.models.enums.ItemGetType; +import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; + +public final class PostViewer extends BaseLanguageActivity { + private ActivityViewerBinding viewerBinding; + private String url, prevUsername, commentsEndCursor; + private ProfileModel profileModel; + private BasePostModel postModel; + private ViewerPostModel viewerPostModel; + private SimpleExoPlayer player; + private ArrayAdapter profileDialogAdapter; + private View viewsContainer, viewerCaptionParent; + private GestureDetectorCompat gestureDetector; + private SwipeEvent swipeEvent; + private CharSequence postCaption = null, postShortCode; + private Resources resources; + private boolean session = false, isFromShare; + private int slidePos = 0, lastSlidePos = 0; + private ItemGetType itemGetType; + @SuppressLint("ClickableViewAccessibility") + final View.OnTouchListener gestureTouchListener = new View.OnTouchListener() { + private float startX; + private float startY; + + @Override + public boolean onTouch(final View v, final MotionEvent event) { + if (v == viewerCaptionParent) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + startX = event.getX(); + startY = event.getY(); + break; + + case MotionEvent.ACTION_UP: + if (!(Utils.isEmpty(postCaption) || + Math.abs(startX - event.getX()) > 50 || Math.abs(startY - event.getY()) > 50)) { + Utils.copyText(PostViewer.this, postCaption); + return false; + } + } + } + return gestureDetector.onTouchEvent(event); + } + }; + private final DialogInterface.OnClickListener profileDialogListener = (dialog, which) -> { + final String username = viewerPostModel.getUsername(); + + if (which == 0) { + searchUsername(username); + } else if (profileModel != null && which == 1) { + startActivity(new Intent(this, ProfileViewer.class) + .putExtra(Constants.EXTRAS_PROFILE, profileModel)); + } + }; + private final View.OnClickListener onClickListener = new View.OnClickListener() { + @Override + public void onClick(final View v) { + if (v == viewerBinding.topPanel.ivProfilePic) { + new AlertDialog.Builder(PostViewer.this).setAdapter(profileDialogAdapter, profileDialogListener) + .setNeutralButton(R.string.cancel, null).setTitle(viewerPostModel.getUsername()).show(); + + } else if (v == viewerBinding.ivToggleFullScreen) { + toggleFullscreen(); + + final LinearLayout topPanelRoot = viewerBinding.topPanel.getRoot(); + final int iconRes; + + if (containerLayoutParams.height == 0) { + containerLayoutParams.height = LinearLayout.LayoutParams.MATCH_PARENT; + iconRes = R.drawable.ic_fullscreen_exit; + topPanelRoot.setVisibility(View.GONE); + viewerBinding.btnDownload.setVisibility(View.VISIBLE); + } else { + containerLayoutParams.height = 0; + iconRes = R.drawable.ic_fullscreen; + topPanelRoot.setVisibility(View.VISIBLE); + viewerBinding.btnDownload.setVisibility(View.GONE); + } + + viewerBinding.ivToggleFullScreen.setImageResource(iconRes); + viewerBinding.container.setLayoutParams(containerLayoutParams); + + } else if (v == viewerBinding.bottomPanel.btnMute) { + if (player != null) { + final float intVol = player.getVolume() == 0f ? 1f : 0f; + player.setVolume(intVol); + viewerBinding.bottomPanel.btnMute.setImageResource(intVol == 0f ? R.drawable.vol : R.drawable.mute); + Utils.sessionVolumeFull = intVol == 1f; + } + + } else { + final Object tag = v.getTag(); + if (tag instanceof ViewerPostModel) { + viewerPostModel = (ViewerPostModel) tag; + slidePos = Math.max(0, viewerPostModel.getPosition()); + refreshPost(); + } + } + } + }; + private final View.OnClickListener downloadClickListener = v -> { + if (ContextCompat.checkSelfPermission(this, Utils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) + showDownloadDialog(); + else + ActivityCompat.requestPermissions(this, Utils.PERMS, 8020); + }; + private final PostsMediaAdapter mediaAdapter = new PostsMediaAdapter(null, onClickListener); + private RequestManager glideRequestManager; + private LinearLayout.LayoutParams containerLayoutParams; + + @Override + protected void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + viewerBinding = ActivityViewerBinding.inflate(getLayoutInflater()); + setContentView(viewerBinding.getRoot()); + + glideRequestManager = Glide.with(this); + + final Intent intent = getIntent(); + if (intent == null || !intent.hasExtra(Constants.EXTRAS_POST) + || (postModel = (PostModel) intent.getSerializableExtra(Constants.EXTRAS_POST)) == null) { + Utils.errorFinish(this); + return; + } + + containerLayoutParams = (LinearLayout.LayoutParams) viewerBinding.container.getLayoutParams(); + + if (intent.hasExtra(Constants.EXTRAS_TYPE)) + itemGetType = (ItemGetType) intent.getSerializableExtra(Constants.EXTRAS_TYPE); + + resources = getResources(); + + final View viewStoryPost = findViewById(R.id.viewStoryPost); + if (viewStoryPost != null) viewStoryPost.setVisibility(View.GONE); + + viewerBinding.topPanel.title.setMovementMethod(new LinkMovementMethod()); + viewerBinding.topPanel.title.setMentionClickListener((view, text, isHashtag) -> + onClickListener.onClick(viewerBinding.topPanel.ivProfilePic)); + viewerBinding.topPanel.ivProfilePic.setOnClickListener(onClickListener); + + viewerBinding.ivToggleFullScreen.setOnClickListener(onClickListener); + viewerBinding.btnDownload.setOnClickListener(downloadClickListener); + + profileDialogAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, + new String[]{resources.getString(R.string.open_profile), resources.getString(R.string.view_pfp)}); + + postModel.setPosition(intent.getIntExtra(Constants.EXTRAS_INDEX, -1)); + postShortCode = postModel.getShortCode(); + + final boolean postIdNull = postModel.getPostId() == null; + if (!postIdNull) + setupPostInfoBar(intent.getStringExtra(Constants.EXTRAS_USER), postModel.getItemType()); + + isFromShare = postModel.getPosition() == -1 || postIdNull; + + viewerCaptionParent = (View) viewerBinding.bottomPanel.viewerCaption.getParent(); + viewsContainer = (View) viewerBinding.bottomPanel.tvVideoViews.getParent(); + + viewerBinding.mediaList.setLayoutManager(new LinearLayoutManager(this, RecyclerView.HORIZONTAL, false)); + viewerBinding.mediaList.setAdapter(mediaAdapter); + viewerBinding.mediaList.setVisibility(View.GONE); + + swipeEvent = isRight -> { + final List itemGetterItems; + final boolean isMainSwipe; + + if (itemGetType != null && Main.itemGetter != null) { + itemGetterItems = Main.itemGetter.get(itemGetType); + isMainSwipe = !(itemGetterItems.size() < 1 || itemGetType == ItemGetType.MAIN_ITEMS && isFromShare); + } else { + itemGetterItems = null; + isMainSwipe = false; + } + + final BasePostModel[] basePostModels = mediaAdapter != null ? mediaAdapter.getPostModels() : null; + final int slides = basePostModels != null ? basePostModels.length : 0; + + int position = postModel.getPosition(); + + if (isRight) { + --slidePos; + if (!isMainSwipe && slidePos < 0) slidePos = 0; + if (slides > 0 && slidePos >= 0) { + if (basePostModels[slidePos] instanceof ViewerPostModel) { + viewerPostModel = (ViewerPostModel) basePostModels[slidePos]; + } + refreshPost(); + return; + } + if (isMainSwipe && --position < 0) position = itemGetterItems.size() - 1; + } else { + ++slidePos; + if (!isMainSwipe && slidePos >= slides) slidePos = slides - 1; + if (slides > 0 && slidePos < slides) { + if (basePostModels[slidePos] instanceof ViewerPostModel) { + viewerPostModel = (ViewerPostModel) basePostModels[slidePos]; + } + refreshPost(); + return; + } + if (isMainSwipe && ++position >= itemGetterItems.size()) position = 0; + } + + if (isMainSwipe) { + slidePos = 0; + Log.d("AWAISKING_APP", "swipe left <<< post[" + position + "]: " + postModel + " -- " + slides); + postModel = itemGetterItems.get(position); + postModel.setPosition(position); + viewPost(); + } + }; + gestureDetector = new GestureDetectorCompat(this, new SwipeGestureListener(swipeEvent)); + + viewPost(); + } + + private void viewPost() { + lastSlidePos = 0; + mediaAdapter.setData(null); + viewsContainer.setVisibility(View.GONE); + viewerCaptionParent.setVisibility(View.GONE); + viewerBinding.mediaList.setVisibility(View.GONE); + viewerBinding.btnDownload.setVisibility(View.GONE); + viewerBinding.bottomPanel.btnMute.setVisibility(View.GONE); + viewerBinding.bottomPanel.tvPostDate.setVisibility(View.GONE); + viewerBinding.bottomPanel.btnComments.setVisibility(View.GONE); + viewerBinding.bottomPanel.btnDownload.setVisibility(View.INVISIBLE); + viewerBinding.bottomPanel.viewerCaption.setText(null); + viewerBinding.bottomPanel.viewerCaption.setMentionClickListener(null); + + viewerBinding.playerView.setVisibility(View.GONE); + viewerBinding.playerView.setPlayer(null); + viewerBinding.imageViewer.setImageResource(0); + viewerBinding.imageViewer.setImageDrawable(null); + + new PostFetcher(postModel.getShortCode(), result -> { + if (result == null || result.length < 1) { + Toast.makeText(this, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); + return; + } + + viewerPostModel = result[0]; + commentsEndCursor = viewerPostModel.getCommentsEndCursor(); + + mediaAdapter.setData(result); + if (result.length > 1) { + viewerBinding.mediaList.setVisibility(View.VISIBLE); + } + + viewerCaptionParent.setOnTouchListener(gestureTouchListener); + viewerBinding.playerView.setOnTouchListener(gestureTouchListener); + viewerBinding.imageViewer.setOnSingleFlingListener((e1, e2, velocityX, velocityY) -> { + final float diffX = e2.getX() - e1.getX(); + if (Math.abs(diffX) > Math.abs(e2.getY() - e1.getY()) && Math.abs(diffX) > SwipeGestureListener.SWIPE_THRESHOLD + && Math.abs(velocityX) > SwipeGestureListener.SWIPE_VELOCITY_THRESHOLD) { + swipeEvent.onSwipe(diffX > 0); + return true; + } + return false; + }); + + final long commentsCount = viewerPostModel.getCommentsCount(); + viewerBinding.bottomPanel.commentsCount.setText(String.valueOf(commentsCount)); + viewerBinding.bottomPanel.btnComments.setVisibility(View.VISIBLE); + + if (commentsCount > 0) { + viewerBinding.bottomPanel.btnComments.setOnClickListener(v -> + startActivityForResult(new Intent(this, CommentsViewer.class) + .putExtra(Constants.EXTRAS_END_CURSOR, commentsEndCursor) + .putExtra(Constants.EXTRAS_SHORTCODE, postShortCode), 6969)); + viewerBinding.bottomPanel.btnComments.setClickable(true); + viewerBinding.bottomPanel.btnComments.setEnabled(true); + } else { + viewerBinding.bottomPanel.btnComments.setOnClickListener(null); + viewerBinding.bottomPanel.btnComments.setClickable(false); + viewerBinding.bottomPanel.btnComments.setEnabled(false); + } + + if (postModel instanceof PostModel) { + final PostModel postModel = (PostModel) this.postModel; + postModel.setPostId(viewerPostModel.getPostId()); + postModel.setTimestamp(viewerPostModel.getTimestamp()); + postModel.setPostCaption(viewerPostModel.getPostCaption()); + } + + setupPostInfoBar(viewerPostModel.getUsername(), viewerPostModel.getItemType()); + + postCaption = postModel.getPostCaption(); + viewerCaptionParent.setVisibility(View.VISIBLE); + + viewerBinding.bottomPanel.btnDownload.setOnClickListener(downloadClickListener); + + refreshPost(); + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + private void searchUsername(final String text) { + if (Main.scanHack != null) { + Main.scanHack.onResult(text); + finish(); + } + } + + private void setupVideo() { + viewerBinding.playerView.setVisibility(View.VISIBLE); + viewerBinding.bottomPanel.btnDownload.setVisibility(View.VISIBLE); + viewerBinding.bottomPanel.btnMute.setVisibility(View.VISIBLE); + viewsContainer.setVisibility(View.VISIBLE); + viewerBinding.progressView.setVisibility(View.GONE); + viewerBinding.imageViewer.setVisibility(View.GONE); + viewerBinding.imageViewer.setImageDrawable(null); + + viewerBinding.bottomPanel.tvVideoViews.setText(String.valueOf(viewerPostModel.getVideoViews())); + + player = new SimpleExoPlayer.Builder(this).build(); + viewerBinding.playerView.setPlayer(player); + float vol = Utils.settingsHelper.getBoolean(Constants.MUTED_VIDEOS) ? 0f : 1f; + if (vol == 0f && Utils.sessionVolumeFull) vol = 1f; + + player.setVolume(vol); + player.setPlayWhenReady(Utils.settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS)); + final ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(new DefaultDataSourceFactory(this, "instagram")) + .createMediaSource(Uri.parse(url)); + mediaSource.addEventListener(new Handler(), new MediaSourceEventListener() { + @Override + public void onLoadCompleted(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + viewerBinding.progressView.setVisibility(View.GONE); + } + + @Override + public void onLoadStarted(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + viewerBinding.progressView.setVisibility(View.VISIBLE); + } + + @Override + public void onLoadCanceled(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + viewerBinding.progressView.setVisibility(View.GONE); + } + + @Override + public void onLoadError(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData, final IOException error, final boolean wasCanceled) { + viewerBinding.progressView.setVisibility(View.GONE); + } + }); + player.prepare(mediaSource); + + player.setVolume(vol); + viewerBinding.bottomPanel.btnMute.setImageResource(vol == 0f ? R.drawable.vol : R.drawable.mute); + + viewerBinding.bottomPanel.btnMute.setOnClickListener(onClickListener); + } + + private void setupImage() { + viewsContainer.setVisibility(View.GONE); + viewerBinding.playerView.setVisibility(View.GONE); + viewerBinding.progressView.setVisibility(View.VISIBLE); + viewerBinding.bottomPanel.btnMute.setVisibility(View.GONE); + viewerBinding.bottomPanel.btnDownload.setVisibility(View.VISIBLE); + + viewerBinding.imageViewer.setImageDrawable(null); + viewerBinding.imageViewer.setVisibility(View.VISIBLE); + viewerBinding.imageViewer.setZoomable(true); + viewerBinding.imageViewer.setZoomTransitionDuration(420); + viewerBinding.imageViewer.setMaximumScale(7.2f); + + glideRequestManager.load(url).listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable final GlideException e, final Object model, final Target target, final boolean isFirstResource) { + viewerBinding.progressView.setVisibility(View.GONE); + return false; + } + + @Override + public boolean onResourceReady(final Drawable resource, final Object model, final Target target, final DataSource dataSource, final boolean isFirstResource) { + viewerBinding.progressView.setVisibility(View.GONE); + return false; + } + }).into(viewerBinding.imageViewer); + } + + private void showDownloadDialog() { + final ArrayList postModels = new ArrayList<>(); + + if (!session && viewerBinding.mediaList.getVisibility() == View.VISIBLE) { + final DialogInterface.OnClickListener clickListener = (dialog, which) -> { + postModels.clear(); + + if (which == DialogInterface.BUTTON_NEGATIVE) { + final BasePostModel[] adapterPostModels = mediaAdapter.getPostModels(); + for (int i = 0, size = mediaAdapter.getItemCount(); i < size; ++i) { + if (adapterPostModels[i] instanceof ViewerPostModel) + postModels.add(adapterPostModels[i]); + } + } else if (which == DialogInterface.BUTTON_POSITIVE) { + postModels.add(viewerPostModel); + } else { + session = true; + postModels.add(viewerPostModel); + } + + if (postModels.size() > 0) + Utils.batchDownload(this, viewerPostModel.getUsername(), DownloadMethod.DOWNLOAD_POST_VIEWER, postModels); + }; + + new AlertDialog.Builder(this).setTitle(R.string.post_viewer_download_dialog_title) + .setMessage(R.string.post_viewer_download_message) + .setNeutralButton(R.string.post_viewer_download_session, clickListener).setPositiveButton(R.string.post_viewer_download_current, clickListener) + .setNegativeButton(R.string.post_viewer_download_album, clickListener).show(); + } else { + Utils.batchDownload(this, viewerPostModel.getUsername(), DownloadMethod.DOWNLOAD_POST_VIEWER, Collections.singletonList(viewerPostModel)); + } + } + + @Override + public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == 8020 && grantResults[0] == PackageManager.PERMISSION_GRANTED) + showDownloadDialog(); + } + + @Override + protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == 6969) { + setResult(RESULT_OK); + finish(); + } + } + + @Override + public void onPause() { + super.onPause(); + if (Build.VERSION.SDK_INT < 24) releasePlayer(); + } + + @Override + public void onStop() { + super.onStop(); + if (Build.VERSION.SDK_INT >= 24) releasePlayer(); + } + + @Override + protected void onResume() { + super.onResume(); + if (player == null && viewerPostModel != null && viewerPostModel.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO) + setupVideo(); + else if (player != null) { + player.setPlayWhenReady(true); + player.getPlaybackState(); + } + } + + private void refreshPost() { + postShortCode = postModel.getShortCode(); + if (viewerBinding.mediaList.getVisibility() == View.VISIBLE) { + ViewerPostModel item = mediaAdapter.getItemAt(lastSlidePos); + if (item != null) { + item.setCurrentSlide(false); + mediaAdapter.notifyItemChanged(lastSlidePos, item); + } + + item = mediaAdapter.getItemAt(slidePos); + if (item != null) { + item.setCurrentSlide(true); + mediaAdapter.notifyItemChanged(slidePos, item); + } + } + lastSlidePos = slidePos; + + postCaption = viewerPostModel.getPostCaption(); + + if (Utils.hasMentions(postCaption)) { + viewerBinding.bottomPanel.viewerCaption.setText(Utils.getMentionText(postCaption), TextView.BufferType.SPANNABLE); + viewerBinding.bottomPanel.viewerCaption.setMentionClickListener((view, text, isHashtag) -> + new AlertDialog.Builder(PostViewer.this).setTitle(text) + .setMessage(isHashtag ? R.string.comment_view_mention_hash_search : R.string.comment_view_mention_user_search) + .setNegativeButton(R.string.cancel, null).setPositiveButton(R.string.ok, + (dialog, which) -> searchUsername(text)).show()); + } else { + viewerBinding.bottomPanel.viewerCaption.setMentionClickListener(null); + viewerBinding.bottomPanel.viewerCaption.setText(postCaption); + } + + setupPostInfoBar(viewerPostModel.getUsername(), viewerPostModel.getItemType()); + + if (postModel instanceof PostModel) { + final PostModel postModel = (PostModel) this.postModel; + postModel.setPostId(viewerPostModel.getPostId()); + postModel.setTimestamp(viewerPostModel.getTimestamp()); + postModel.setPostCaption(viewerPostModel.getPostCaption()); + } + + viewerBinding.bottomPanel.tvPostDate.setText(viewerPostModel.getPostDate()); + viewerBinding.bottomPanel.tvPostDate.setVisibility(View.VISIBLE); + viewerBinding.bottomPanel.tvPostDate.setSelected(true); + + url = viewerPostModel.getDisplayUrl(); + releasePlayer(); + + viewerBinding.btnDownload.setVisibility(containerLayoutParams.height == 0 ? View.GONE : View.VISIBLE); + if (viewerPostModel.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO) setupVideo(); + else setupImage(); + } + + private void releasePlayer() { + if (player != null) { + player.release(); + player = null; + } + } + + private void setupPostInfoBar(final String from, final MediaItemType mediaItemType) { + if (prevUsername == null || !prevUsername.equals(from)) { + viewerBinding.topPanel.ivProfilePic.setImageBitmap(null); + viewerBinding.topPanel.ivProfilePic.setImageDrawable(null); + viewerBinding.topPanel.ivProfilePic.setImageResource(0); + + if (from.charAt(0) != '#') + new ProfileFetcher(from, result -> { + profileModel = result; + + if (result != null) { + final String hdProfilePic = result.getHdProfilePic(); + final String sdProfilePic = result.getSdProfilePic(); + + final boolean hdPicEmpty = Utils.isEmpty(hdProfilePic); + glideRequestManager.load(hdPicEmpty ? sdProfilePic : hdProfilePic).listener(new RequestListener() { + private boolean loaded = true; + + @Override + public boolean onLoadFailed(@Nullable final GlideException e, final Object model, final Target target, final boolean isFirstResource) { + viewerBinding.topPanel.ivProfilePic.setEnabled(false); + viewerBinding.topPanel.ivProfilePic.setOnClickListener(null); + if (loaded) { + loaded = false; + if (!Utils.isEmpty(sdProfilePic)) glideRequestManager.load(sdProfilePic).listener(this) + .into(viewerBinding.topPanel.ivProfilePic); + } + return false; + } + + @Override + public boolean onResourceReady(final Drawable resource, final Object model, final Target target, final DataSource dataSource, final boolean isFirstResource) { + viewerBinding.topPanel.ivProfilePic.setEnabled(true); + viewerBinding.topPanel.ivProfilePic.setOnClickListener(onClickListener); + return false; + } + }).into(viewerBinding.topPanel.ivProfilePic); + } + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + prevUsername = from; + } + + final String titlePrefix = resources.getString(mediaItemType == MediaItemType.MEDIA_TYPE_VIDEO ? + R.string.post_viewer_video_post : R.string.post_viewer_image_post); + if (Utils.isEmpty(from)) viewerBinding.topPanel.title.setText(titlePrefix); + else { + final CharSequence titleText = resources.getString(R.string.post_viewer_post_from, titlePrefix, from) + " "; + final int titleLen = titleText.length(); + final SpannableString spannableString = new SpannableString(titleText); + spannableString.setSpan(new CommentMentionClickSpan(), titleLen - from.length() - 1, titleLen - 1, 0); + viewerBinding.topPanel.title.setText(spannableString); + } + } + + private void toggleFullscreen() { + final View decorView = getWindow().getDecorView(); + int newUiOptions = decorView.getSystemUiVisibility(); + newUiOptions ^= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + newUiOptions ^= View.SYSTEM_UI_FLAG_FULLSCREEN; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) + newUiOptions ^= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + decorView.setSystemUiVisibility(newUiOptions); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/activities/ProfileViewer.java b/app/src/main/java/awais/instagrabber/activities/ProfileViewer.java new file mode 100755 index 00000000..c6bc5a80 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/activities/ProfileViewer.java @@ -0,0 +1,215 @@ +package awais.instagrabber.activities; + +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Environment; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.Toast; + +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentManager; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; + +import java.io.File; + +import awais.instagrabber.R; +import awais.instagrabber.asyncs.DownloadAsync; +import awais.instagrabber.asyncs.ProfilePictureFetcher; +import awais.instagrabber.databinding.ActivityProfileBinding; +import awais.instagrabber.dialogs.ProfileSettingsDialog; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.models.enums.ProfilePictureFetchMode; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; + +import static awais.instagrabber.utils.Constants.PROFILE_FETCH_MODE; + +public final class ProfileViewer extends BaseLanguageActivity { + private final ProfilePictureFetchMode[] fetchModes = { + ProfilePictureFetchMode.INSTADP, + ProfilePictureFetchMode.INSTA_STALKER, + ProfilePictureFetchMode.INSTAFULLSIZE, + }; + private ActivityProfileBinding profileBinding; + private ProfileModel profileModel; + private MenuItem menuItemDownload; + private String profilePicUrl; + private FragmentManager fragmentManager; + private FetchListener fetchListener; + private boolean errorHandled = false; + private boolean fallbackToProfile = false; + + @Override + protected void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + profileBinding = ActivityProfileBinding.inflate(getLayoutInflater()); + setContentView(profileBinding.getRoot()); + + setSupportActionBar(profileBinding.toolbar.toolbar); + + final Intent intent = getIntent(); + if (intent == null || !intent.hasExtra(Constants.EXTRAS_PROFILE) + || (profileModel = (ProfileModel) intent.getSerializableExtra(Constants.EXTRAS_PROFILE)) == null) { + Utils.errorFinish(this); + return; + } + + fragmentManager = getSupportFragmentManager(); + + final String id = profileModel.getId(); + final String username = profileModel.getUsername(); + + profileBinding.toolbar.toolbar.setTitle(username); + + profileBinding.progressView.setVisibility(View.VISIBLE); + profileBinding.imageViewer.setVisibility(View.VISIBLE); + + profileBinding.imageViewer.setZoomable(true); + profileBinding.imageViewer.setZoomTransitionDuration(420); + profileBinding.imageViewer.setMaximumScale(7.2f); + + final int fetchIndex = Math.min(2, Math.max(0, Utils.settingsHelper.getInteger(PROFILE_FETCH_MODE))); + final ProfilePictureFetchMode fetchMode = fetchModes[fetchIndex]; + + fetchListener = profileUrl -> { + profilePicUrl = profileUrl; + + if (!fallbackToProfile && Utils.isEmpty(profilePicUrl)) { + fallbackToProfile = true; + new ProfilePictureFetcher(username, id, fetchListener, fetchMode).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + return; + } + + if (errorHandled && fallbackToProfile || Utils.isEmpty(profilePicUrl)) + profilePicUrl = profileModel.getHdProfilePic(); + + final RequestManager glideRequestManager = Glide.with(this); + + glideRequestManager.load(profilePicUrl).addListener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable final GlideException e, final Object model, final Target target, final boolean isFirstResource) { + fallbackToProfile = true; + if (!errorHandled) { + errorHandled = true; + new ProfilePictureFetcher(username, id, fetchListener, fetchModes[Math.min(2, Math.max(0, fetchIndex + 1))]) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else { + glideRequestManager.load(profileModel.getHdProfilePic()).into(profileBinding.imageViewer); + showImageInfo(); + } + profileBinding.progressView.setVisibility(View.GONE); + return false; + } + + @Override + public boolean onResourceReady(final Drawable resource, final Object model, final Target target, final DataSource dataSource, final boolean isFirstResource) { + if (menuItemDownload != null) menuItemDownload.setEnabled(true); + showImageInfo(); + profileBinding.progressView.setVisibility(View.GONE); + return false; + } + + private void showImageInfo() { + final Drawable drawable = profileBinding.imageViewer.getDrawable(); + if (drawable != null) { + final StringBuilder info = new StringBuilder(getString(R.string.profile_viewer_imageinfo, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight())); + if (drawable instanceof BitmapDrawable) { + final Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); + if (bitmap != null) { + final String colorDepthPrefix = getString(R.string.profile_viewer_colordepth_prefix); + switch (bitmap.getConfig()) { + case ALPHA_8: + info.append(colorDepthPrefix).append(" 8-bits(A)"); + break; + case RGB_565: + info.append(colorDepthPrefix).append(" 16-bits-A"); + break; + case ARGB_4444: + info.append(colorDepthPrefix).append(" 16-bits+A"); + break; + case ARGB_8888: + info.append(colorDepthPrefix).append(" 32-bits+A"); + break; + case RGBA_F16: + info.append(colorDepthPrefix).append(" 64-bits+A"); + break; + case HARDWARE: + info.append(colorDepthPrefix).append(" auto"); + break; + } + } + } + profileBinding.imageInfo.setText(info); + profileBinding.imageInfo.setVisibility(View.VISIBLE); + } + } + }).into(profileBinding.imageViewer); + }; + + new ProfilePictureFetcher(username, id, fetchListener, fetchMode).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + private void downloadProfilePicture() { + int error = 0; + + if (profileModel != null) { + final File dir = new File(Environment.getExternalStorageDirectory(), "Download"); + if (dir.exists() || dir.mkdirs()) { + + final File saveFile = new File(dir, profileModel.getUsername() + '_' + System.currentTimeMillis() + + Utils.getExtensionFromModel(profilePicUrl, profileModel)); + + new DownloadAsync(this, + profilePicUrl, + saveFile, + result -> { + final int toastRes = result != null && result.exists() ? + R.string.downloader_downloaded_in_folder : R.string.downloader_error_download_file; + Toast.makeText(this, toastRes, Toast.LENGTH_SHORT).show(); + }).setItems(null, profileModel.getUsername()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else error = 1; + } else error = 2; + + if (error == 1) Toast.makeText(this, R.string.downloader_error_creating_folder, Toast.LENGTH_SHORT).show(); + else if (error == 2) Toast.makeText(this, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); + } + + @Override + public boolean onCreateOptionsMenu(final Menu menu) { + getMenuInflater().inflate(R.menu.menu, menu); + + final MenuItem.OnMenuItemClickListener menuItemClickListener = item -> { + if (item == menuItemDownload) { + downloadProfilePicture(); + } else { + new ProfileSettingsDialog().show(fragmentManager, "settings"); + } + return true; + }; + + menu.findItem(R.id.action_search).setVisible(false); + menuItemDownload = menu.findItem(R.id.action_download); + menuItemDownload.setVisible(true); + menuItemDownload.setEnabled(false); + menuItemDownload.setOnMenuItemClickListener(menuItemClickListener); + + final MenuItem menuItemSettings = menu.findItem(R.id.action_settings); + menuItemSettings.setVisible(true); + menuItemSettings.setOnMenuItemClickListener(menuItemClickListener); + + return true; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/activities/StoryViewer.java b/app/src/main/java/awais/instagrabber/activities/StoryViewer.java new file mode 100755 index 00000000..01cf541e --- /dev/null +++ b/app/src/main/java/awais/instagrabber/activities/StoryViewer.java @@ -0,0 +1,354 @@ +package awais.instagrabber.activities; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Bundle; +import android.os.Environment; +import android.os.Handler; +import android.util.Log; +import android.util.Pair; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.core.view.GestureDetectorCompat; +import androidx.recyclerview.widget.LinearLayoutManager; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.source.MediaSourceEventListener; +import com.google.android.exoplayer2.source.ProgressiveMediaSource; +import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; + +import java.io.File; +import java.io.IOException; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.R; +import awais.instagrabber.adapters.StoriesAdapter; +import awais.instagrabber.asyncs.DownloadAsync; +import awais.instagrabber.customviews.helpers.SwipeGestureListener; +import awais.instagrabber.databinding.ActivityStoryViewerBinding; +import awais.instagrabber.interfaces.SwipeEvent; +import awais.instagrabber.models.PostModel; +import awais.instagrabber.models.StoryModel; +import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; +import awaisomereport.LogCollector; + +import static awais.instagrabber.customviews.helpers.SwipeGestureListener.SWIPE_THRESHOLD; +import static awais.instagrabber.customviews.helpers.SwipeGestureListener.SWIPE_VELOCITY_THRESHOLD; +import static awais.instagrabber.utils.Constants.FOLDER_PATH; +import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO; +import static awais.instagrabber.utils.Utils.logCollector; +import static awais.instagrabber.utils.Utils.settingsHelper; + +public final class StoryViewer extends BaseLanguageActivity { + private final StoriesAdapter storiesAdapter = new StoriesAdapter(null, new View.OnClickListener() { + @Override + public void onClick(final View v) { + final Object tag = v.getTag(); + if (tag instanceof StoryModel) { + currentStory = (StoryModel) tag; + slidePos = currentStory.getPosition(); + refreshStory(); + } + } + }); + private ActivityStoryViewerBinding storyViewerBinding; + private StoryModel[] storyModels; + private GestureDetectorCompat gestureDetector; + private SimpleExoPlayer player; + private SwipeEvent swipeEvent; + private MenuItem menuDownload; + private StoryModel currentStory; + private String url, username; + private int slidePos = 0, lastSlidePos = 0; + + @Override + protected void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + storyViewerBinding = ActivityStoryViewerBinding.inflate(getLayoutInflater()); + setContentView(storyViewerBinding.getRoot()); + + setSupportActionBar(storyViewerBinding.toolbar.toolbar); + + final Intent intent = getIntent(); + if (intent == null || !intent.hasExtra(Constants.EXTRAS_STORIES) + || (storyModels = (StoryModel[]) intent.getSerializableExtra(Constants.EXTRAS_STORIES)) == null) { + Utils.errorFinish(this); + return; + } + + username = intent.getStringExtra(Constants.EXTRAS_USERNAME); + final String highlight = intent.getStringExtra(Constants.EXTRAS_HIGHLIGHT); + final boolean hasUsername = !Utils.isEmpty(username); + final boolean hasHighlight = !Utils.isEmpty(highlight); + + if (hasUsername) { + storyViewerBinding.toolbar.toolbar.setTitle(username); + if (hasHighlight) storyViewerBinding.toolbar.toolbar.setSubtitle(getString(R.string.title_highlight, highlight)); + else storyViewerBinding.toolbar.toolbar.setSubtitle(R.string.title_user_story); + } + + storyViewerBinding.storiesList.setVisibility(View.GONE); + storyViewerBinding.storiesList.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); + storyViewerBinding.storiesList.setAdapter(storiesAdapter); + + swipeEvent = new SwipeEvent() { + private final int storiesLen = storyModels != null ? storyModels.length : 0; + + @Override + public void onSwipe(final boolean isRightSwipe) { + if (storyModels != null && storiesLen > 0) { + if (isRightSwipe) { + if (--slidePos <= 0) slidePos = 0; + } else if (++slidePos >= storiesLen) slidePos = storiesLen - 1; + + currentStory = storyModels[slidePos]; + slidePos = currentStory.getPosition(); + refreshStory(); + } + } + }; + gestureDetector = new GestureDetectorCompat(this, new SwipeGestureListener(swipeEvent)); + + viewPost(); + } + + @SuppressLint("ClickableViewAccessibility") + private void viewPost() { + lastSlidePos = 0; + storyViewerBinding.storiesList.setVisibility(View.GONE); + storiesAdapter.setData(null); + + if (menuDownload != null) menuDownload.setVisible(false); + + storyViewerBinding.playerView.setOnTouchListener((v, event) -> gestureDetector.onTouchEvent(event)); + storyViewerBinding.imageViewer.setOnSingleFlingListener((e1, e2, velocityX, velocityY) -> { + final float diffX = e2.getX() - e1.getX(); + try { + if (Math.abs(diffX) > Math.abs(e2.getY() - e1.getY()) && Math.abs(diffX) > SWIPE_THRESHOLD + && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) { + swipeEvent.onSwipe(diffX > 0); + return true; + } + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.ACTIVITY_STORY_VIEWER, "viewPost", + new Pair<>("swipeEvent", swipeEvent), + new Pair<>("diffX", diffX)); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + return false; + }); + + storyViewerBinding.viewStoryPost.setOnClickListener(v -> { + final Object tag = v.getTag(); + if (tag instanceof CharSequence) startActivity(new Intent(this, PostViewer.class) + .putExtra(Constants.EXTRAS_POST, new PostModel(tag.toString()))); + }); + + storiesAdapter.setData(storyModels); + if (storyModels.length > 1) storyViewerBinding.storiesList.setVisibility(View.VISIBLE); + + currentStory = storyModels[0]; + refreshStory(); + } + + private void setupVideo() { + storyViewerBinding.playerView.setVisibility(View.VISIBLE); + storyViewerBinding.progressView.setVisibility(View.GONE); + storyViewerBinding.imageViewer.setVisibility(View.GONE); + storyViewerBinding.imageViewer.setImageDrawable(null); + + player = new SimpleExoPlayer.Builder(this).build(); + storyViewerBinding.playerView.setPlayer(player); + player.setPlayWhenReady(settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS)); + + final ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(new DefaultDataSourceFactory(this, "instagram")) + .createMediaSource(Uri.parse(url)); + mediaSource.addEventListener(new Handler(), new MediaSourceEventListener() { + @Override + public void onLoadCompleted(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + if (menuDownload != null) menuDownload.setVisible(true); + storyViewerBinding.progressView.setVisibility(View.GONE); + } + + @Override + public void onLoadStarted(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + if (menuDownload != null) menuDownload.setVisible(true); + storyViewerBinding.progressView.setVisibility(View.VISIBLE); + } + + @Override + public void onLoadCanceled(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + storyViewerBinding.progressView.setVisibility(View.GONE); + } + + @Override + public void onLoadError(final int windowIndex, @Nullable final MediaSource.MediaPeriodId mediaPeriodId, final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData, final IOException error, final boolean wasCanceled) { + if (menuDownload != null) menuDownload.setVisible(false); + storyViewerBinding.progressView.setVisibility(View.GONE); + } + }); + player.prepare(mediaSource); + + storyViewerBinding.playerView.setOnClickListener(v -> { + if (player != null) { + if (player.getPlaybackState() == Player.STATE_ENDED) player.seekTo(0); + player.setPlayWhenReady(player.getPlaybackState() == Player.STATE_ENDED || !player.isPlaying()); + } + }); + } + + private void setupImage() { + storyViewerBinding.progressView.setVisibility(View.VISIBLE); + storyViewerBinding.playerView.setVisibility(View.GONE); + + storyViewerBinding.imageViewer.setImageDrawable(null); + storyViewerBinding.imageViewer.setVisibility(View.VISIBLE); + storyViewerBinding.imageViewer.setZoomable(true); + storyViewerBinding.imageViewer.setZoomTransitionDuration(420); + storyViewerBinding.imageViewer.setMaximumScale(7.2f); + + Glide.with(this).load(url).listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable final GlideException e, final Object model, final Target target, final boolean isFirstResource) { + storyViewerBinding.progressView.setVisibility(View.GONE); + return false; + } + + @Override + public boolean onResourceReady(final Drawable resource, final Object model, final Target target, final DataSource dataSource, final boolean isFirstResource) { + if (menuDownload != null) menuDownload.setVisible(true); + storyViewerBinding.progressView.setVisibility(View.GONE); + return false; + } + }).into(storyViewerBinding.imageViewer); + } + + @Override + public boolean onCreateOptionsMenu(final Menu menu) { + getMenuInflater().inflate(R.menu.menu, menu); + + menu.findItem(R.id.action_settings).setVisible(false); + menu.findItem(R.id.action_search).setVisible(false); + + menuDownload = menu.findItem(R.id.action_download); + menuDownload.setVisible(true); + menuDownload.setOnMenuItemClickListener(item -> { + if (ContextCompat.checkSelfPermission(this, Utils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) + downloadStory(); + else + ActivityCompat.requestPermissions(this, Utils.PERMS, 8020); + return true; + }); + + return true; + } + + @Override + public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == 8020 && grantResults[0] == PackageManager.PERMISSION_GRANTED) downloadStory(); + } + + @Override + public void onPause() { + super.onPause(); + if (Build.VERSION.SDK_INT < 24) releasePlayer(); + } + + @Override + public void onStop() { + super.onStop(); + if (Build.VERSION.SDK_INT >= 24) releasePlayer(); + } + + private void downloadStory() { + int error = 0; + if (currentStory != null) { + File dir = new File(Environment.getExternalStorageDirectory(), "Download"); + + if (settingsHelper.getBoolean(FOLDER_SAVE_TO)) { + final String customPath = settingsHelper.getString(FOLDER_PATH); + if (!Utils.isEmpty(customPath)) dir = new File(customPath); + } + + if (settingsHelper.getBoolean(Constants.DOWNLOAD_USER_FOLDER) && !Utils.isEmpty(username)) + dir = new File(dir, username); + + if (dir.exists() || dir.mkdirs()) { + final String storyUrl = currentStory.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO ? currentStory.getVideoUrl() : currentStory.getStoryUrl(); + final File saveFile = new File(dir, currentStory.getStoryMediaId() + "_" + currentStory.getTimestamp() + + Utils.getExtensionFromModel(storyUrl, currentStory)); + + new DownloadAsync(this, storyUrl, saveFile, result -> { + final int toastRes = result != null && result.exists() ? R.string.downloader_complete + : R.string.downloader_error_download_file; + Toast.makeText(this, toastRes, Toast.LENGTH_SHORT).show(); + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + + } else error = 1; + } else error = 2; + + if (error == 1) Toast.makeText(this, R.string.downloader_error_creating_folder, Toast.LENGTH_SHORT).show(); + else if (error == 2) Toast.makeText(this, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); + } + + private void refreshStory() { + if (storyViewerBinding.storiesList.getVisibility() == View.VISIBLE) { + StoryModel item = storiesAdapter.getItemAt(lastSlidePos); + if (item != null) { + item.setCurrentSlide(false); + storiesAdapter.notifyItemChanged(lastSlidePos, item); + } + + item = storiesAdapter.getItemAt(slidePos); + if (item != null) { + item.setCurrentSlide(true); + storiesAdapter.notifyItemChanged(slidePos, item); + } + } + lastSlidePos = slidePos; + + final MediaItemType itemType = currentStory.getItemType(); + + if (menuDownload != null) menuDownload.setVisible(false); + url = itemType == MediaItemType.MEDIA_TYPE_VIDEO ? currentStory.getVideoUrl() : currentStory.getStoryUrl(); + + final String shortCode = currentStory.getTappableShortCode(); + storyViewerBinding.viewStoryPost.setVisibility(shortCode != null ? View.VISIBLE : View.GONE); + storyViewerBinding.viewStoryPost.setTag(shortCode); + + releasePlayer(); + if (itemType == MediaItemType.MEDIA_TYPE_VIDEO) setupVideo(); + else setupImage(); + } + + private void releasePlayer() { + if (player != null) { + try { player.stop(true); } catch (Exception ignored) { } + try { player.release(); } catch (Exception ignored) { } + player = null; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/CommentsAdapter.java b/app/src/main/java/awais/instagrabber/adapters/CommentsAdapter.java new file mode 100755 index 00000000..69221bf0 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/CommentsAdapter.java @@ -0,0 +1,136 @@ +package awais.instagrabber.adapters; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Filter; +import android.widget.Filterable; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; + +import java.util.ArrayList; + +import awais.instagrabber.R; +import awais.instagrabber.adapters.viewholder.CommentViewHolder; +import awais.instagrabber.interfaces.MentionClickListener; +import awais.instagrabber.models.CommentModel; +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.utils.LocaleUtils; +import awais.instagrabber.utils.Utils; + +public final class CommentsAdapter extends RecyclerView.Adapter implements Filterable { + private final boolean isParent; + private final Filter filter = new Filter() { + @NonNull + @Override + protected FilterResults performFiltering(final CharSequence filter) { + final FilterResults results = new FilterResults(); + results.values = commentModels; + + final int commentsLen = commentModels == null ? 0 : commentModels.length; + if (commentModels != null && commentsLen > 0 && !Utils.isEmpty(filter)) { + final String query = filter.toString().toLowerCase(); + final ArrayList filterList = new ArrayList<>(commentsLen); + + for (final CommentModel commentModel : commentModels) { + final String commentText = commentModel.getText().toString().toLowerCase(); + + if (commentText.contains(query)) filterList.add(commentModel); + else { + final CommentModel[] childCommentModels = commentModel.getChildCommentModels(); + if (childCommentModels != null) { + for (final CommentModel childCommentModel : childCommentModels) { + final String childCommentText = childCommentModel.getText().toString().toLowerCase(); + if (childCommentText.contains(query)) filterList.add(commentModel); + } + } + } + } + filterList.trimToSize(); + results.values = filterList.toArray(new CommentModel[0]); + } + + return results; + } + + @Override + protected void publishResults(final CharSequence constraint, @NonNull final FilterResults results) { + if (results.values instanceof CommentModel[]) { + filteredCommentModels = (CommentModel[]) results.values; + notifyDataSetChanged(); + } + } + }; + private final View.OnClickListener onClickListener; + private final MentionClickListener mentionClickListener; + private final CommentModel[] commentModels; + private final String[] quantityStrings = new String[2]; + private LayoutInflater layoutInflater; + private CommentModel[] filteredCommentModels; + + public CommentsAdapter(final CommentModel[] commentModels, final boolean isParent, final View.OnClickListener onClickListener, + final MentionClickListener mentionClickListener) { + this.commentModels = this.filteredCommentModels = commentModels; + this.isParent = isParent; + this.onClickListener = onClickListener; + this.mentionClickListener = mentionClickListener; + } + + @Override + public Filter getFilter() { + return filter; + } + + @NonNull + @Override + public CommentViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int type) { + final Context context = parent.getContext(); + if (quantityStrings[0] == null) quantityStrings[0] = context.getString(R.string.single_like); + if (quantityStrings[1] == null) quantityStrings[1] = context.getString(R.string.multiple_likes); + if (layoutInflater == null) layoutInflater = LayoutInflater.from(context); + return new CommentViewHolder(layoutInflater.inflate( + isParent ? R.layout.item_comment // parent + : R.layout.item_comment_small, // child + parent, false), onClickListener, mentionClickListener); + } + + @Override + public void onBindViewHolder(@NonNull final CommentViewHolder holder, final int position) { + final CommentModel commentModel = filteredCommentModels[position]; + if (commentModel != null) { + holder.setCommentModel(commentModel); + + holder.setCommment(commentModel.getText()); + holder.setDate(commentModel.getDateTime()); + + final long likes = commentModel.getLikes(); + holder.setLikes(String.format(LocaleUtils.getCurrentLocale(), "%d %s", likes, quantityStrings[likes == 1 ? 0 : 1])); + + final ProfileModel profileModel = commentModel.getProfileModel(); + if (profileModel != null) { + holder.setUsername(profileModel.getUsername()); + + Glide.with(layoutInflater.getContext()) + .applyDefaultRequestOptions(new RequestOptions().skipMemoryCache(true)) + .load(profileModel.getSdProfilePic()).into(holder.getProfilePicView()); + } + + if (holder.isParent()) { + final CommentModel[] childCommentModels = commentModel.getChildCommentModels(); + if (childCommentModels != null && childCommentModels.length > 0) + holder.setChildAdapter(new CommentsAdapter(childCommentModels, false, onClickListener, mentionClickListener)); + else holder.hideChildComments(); + } + } + } + + @Override + public int getItemCount() { + return filteredCommentModels == null ? 0 : filteredCommentModels.length; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/DirectMessagesAdapter.java b/app/src/main/java/awais/instagrabber/adapters/DirectMessagesAdapter.java new file mode 100755 index 00000000..0c8717ab --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/DirectMessagesAdapter.java @@ -0,0 +1,116 @@ +package awais.instagrabber.adapters; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; + +import java.util.ArrayList; + +import awais.instagrabber.R; +import awais.instagrabber.adapters.viewholder.DirectMessageViewHolder; +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.models.direct_messages.DirectItemModel; +import awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemActionLogModel; +import awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemReelShareModel; +import awais.instagrabber.models.direct_messages.InboxThreadModel; +import awais.instagrabber.models.enums.DirectItemType; + +public final class DirectMessagesAdapter extends RecyclerView.Adapter { + private final ArrayList inboxThreadModels; + private final View.OnClickListener onClickListener; + private LayoutInflater layoutInflater; + + public DirectMessagesAdapter(final ArrayList inboxThreadModels, final View.OnClickListener onClickListener) { + this.inboxThreadModels = inboxThreadModels; + this.onClickListener = onClickListener; + } + + @NonNull + @Override + public DirectMessageViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int type) { + if (layoutInflater == null) layoutInflater = LayoutInflater.from(parent.getContext()); + return new DirectMessageViewHolder(layoutInflater.inflate(R.layout.layout_include_simple_item, parent, false), + onClickListener); + } + + @Override + public void onBindViewHolder(@NonNull final DirectMessageViewHolder holder, final int position) { + final InboxThreadModel threadModel = inboxThreadModels.get(position); + final DirectItemModel[] itemModels; + + holder.itemView.setTag(threadModel); + + final RequestManager glideRequestManager = Glide.with(holder.itemView); + + if (threadModel != null && (itemModels = threadModel.getItems()) != null) { + final ProfileModel[] users = threadModel.getUsers(); + + if (users.length > 1) { + holder.ivProfilePic.setVisibility(View.GONE); + holder.multipleProfilePicsContainer.setVisibility(View.VISIBLE); + + for (int i = 0; i < Math.min(3, users.length); ++i) + glideRequestManager.load(users[i].getSdProfilePic()).into(holder.multipleProfilePics[i]); + + } else { + holder.ivProfilePic.setVisibility(View.VISIBLE); + holder.multipleProfilePicsContainer.setVisibility(View.GONE); + + glideRequestManager.load(users[0].getSdProfilePic()).into(holder.ivProfilePic); + } + + holder.tvUsername.setText(threadModel.getThreadTitle()); + + final DirectItemModel lastItemModel = itemModels[itemModels.length - 1]; + final DirectItemType itemType = lastItemModel.getItemType(); + + holder.notTextType.setVisibility(itemType != DirectItemType.TEXT ? View.VISIBLE : View.GONE); + + final Context context = layoutInflater.getContext(); + + final CharSequence messageText; + if (itemType == DirectItemType.TEXT) + messageText = lastItemModel.getText(); + else if (itemType == DirectItemType.LINK) + messageText = context.getString(R.string.direct_messages_sent_link); + else if (itemType == DirectItemType.MEDIA || itemType == DirectItemType.MEDIA_SHARE) + messageText = context.getString(R.string.direct_messages_sent_media); + else if (itemType == DirectItemType.ACTION_LOG) { + final DirectItemActionLogModel logModel = lastItemModel.getActionLogModel(); + messageText = logModel != null ? logModel.getDescription() : "..."; + + } else if (itemType == DirectItemType.REEL_SHARE) { + final DirectItemReelShareModel reelShare = lastItemModel.getReelShare(); + if (reelShare == null) + messageText = context.getString(R.string.direct_messages_sent_media); + else { + final String reelType = reelShare.getType(); + final int textRes; + if ("reply".equals(reelType)) textRes = R.string.direct_messages_replied_story; + else if ("mention".equals(reelType)) textRes = R.string.direct_messages_mention_story; + else if ("reaction".equals(reelType)) textRes = R.string.direct_messages_reacted_story; + else textRes = R.string.direct_messages_sent_media; + + messageText = context.getString(textRes) + " : " + reelShare.getText(); + } + + } else messageText = null; + + holder.tvMessage.setText(messageText); + + holder.tvDate.setText(lastItemModel.getDateTime()); + } + } + + @Override + public int getItemCount() { + return inboxThreadModels == null ? 0 : inboxThreadModels.size(); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/DiscoverAdapter.java b/app/src/main/java/awais/instagrabber/adapters/DiscoverAdapter.java new file mode 100755 index 00000000..ebb0231c --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/DiscoverAdapter.java @@ -0,0 +1,87 @@ +package awais.instagrabber.adapters; + +import android.graphics.drawable.Drawable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; + +import java.util.ArrayList; + +import awais.instagrabber.R; +import awais.instagrabber.adapters.viewholder.DiscoverViewHolder; +import awais.instagrabber.models.DiscoverItemModel; +import awais.instagrabber.models.enums.MediaItemType; + +public final class DiscoverAdapter extends RecyclerView.Adapter { + private final ArrayList discoverItemModels; + private final View.OnClickListener clickListener; + private final View.OnLongClickListener longClickListener; + private LayoutInflater layoutInflater; + public boolean isSelecting = false; + + public DiscoverAdapter(final ArrayList discoverItemModels, final View.OnClickListener clickListener, + final View.OnLongClickListener longClickListener) { + this.discoverItemModels = discoverItemModels; + this.longClickListener = longClickListener; + this.clickListener = clickListener; + } + + @NonNull + @Override + public DiscoverViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) { + if (layoutInflater == null) layoutInflater = LayoutInflater.from(parent.getContext()); + return new DiscoverViewHolder(layoutInflater.inflate(R.layout.item_post, parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull final DiscoverViewHolder holder, final int position) { + final DiscoverItemModel itemModel = discoverItemModels.get(position); + if (itemModel != null) { + itemModel.setPosition(position); + holder.itemView.setTag(itemModel); + + holder.itemView.setOnClickListener(clickListener); + holder.itemView.setOnLongClickListener(longClickListener); + + final MediaItemType mediaType = itemModel.getItemType(); + + holder.typeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO || mediaType == MediaItemType.MEDIA_TYPE_SLIDER + ? View.VISIBLE : View.GONE); + + holder.typeIcon.setImageResource(mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? R.drawable.slider : R.drawable.video); + + holder.selectedView.setVisibility(itemModel.isSelected() ? View.VISIBLE : View.GONE); + holder.progressView.setVisibility(View.VISIBLE); + + Glide.with(layoutInflater.getContext()).load(itemModel.getDisplayUrl()).listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable final GlideException e, final Object model, final Target target, final boolean isFirstResource) { + holder.progressView.setVisibility(View.GONE); + return false; + } + + @Override + public boolean onResourceReady(final Drawable resource, final Object model, final Target target, final DataSource dataSource, final boolean isFirstResource) { + holder.progressView.setVisibility(View.GONE); + return false; + } + }).into(holder.postImage); + + } + } + + @Override + public int getItemCount() { + return discoverItemModels == null ? 0 : discoverItemModels.size(); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/FeedAdapter.java b/app/src/main/java/awais/instagrabber/adapters/FeedAdapter.java new file mode 100755 index 00000000..98d8d8bb --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/FeedAdapter.java @@ -0,0 +1,486 @@ +package awais.instagrabber.adapters; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Typeface; +import android.net.Uri; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.style.StyleSpan; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.github.chrisbanes.photoview.PhotoView; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.source.ProgressiveMediaSource; +import com.google.android.exoplayer2.ui.PlayerView; +import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; + +import java.util.ArrayList; +import java.util.Collections; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.R; +import awais.instagrabber.activities.CommentsViewer; +import awais.instagrabber.activities.PostViewer; +import awais.instagrabber.adapters.viewholder.FeedItemViewHolder; +import awais.instagrabber.customviews.CommentMentionClickSpan; +import awais.instagrabber.customviews.RamboTextView; +import awais.instagrabber.interfaces.MentionClickListener; +import awais.instagrabber.models.BasePostModel; +import awais.instagrabber.models.FeedModel; +import awais.instagrabber.models.PostModel; +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.models.ViewerPostModel; +import awais.instagrabber.models.enums.DownloadMethod; +import awais.instagrabber.models.enums.ItemGetType; +import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; + +import static awais.instagrabber.utils.Utils.settingsHelper; + +public final class FeedAdapter extends RecyclerView.Adapter { + private final static String ellipsize = "… more"; + private final Activity activity; + private final LayoutInflater layoutInflater; + private final ArrayList feedModels; + private final MentionClickListener mentionClickListener; + private final View.OnClickListener clickListener = new View.OnClickListener() { + @Override + public void onClick(@NonNull final View v) { + final Object tag = v.getTag(); + + if (tag instanceof FeedModel) { + final FeedModel feedModel = (FeedModel) tag; + + if (v instanceof RamboTextView) { + if (feedModel.isMentionClicked()) + feedModel.toggleCaption(); + feedModel.setMentionClicked(false); + if (!expandCollapseTextView((RamboTextView) v, feedModel)) + feedModel.toggleCaption(); + + } else { + final int id = v.getId(); + switch (id) { + case R.id.btnComments: + activity.startActivityForResult(new Intent(activity, CommentsViewer.class) + .putExtra(Constants.EXTRAS_SHORTCODE, feedModel.getShortCode()), 6969); + break; + + case R.id.viewStoryPost: + activity.startActivity(new Intent(activity, PostViewer.class) + .putExtra(Constants.EXTRAS_INDEX, feedModel.getPosition()) + .putExtra(Constants.EXTRAS_POST, new PostModel(feedModel.getShortCode())) + .putExtra(Constants.EXTRAS_TYPE, ItemGetType.FEED_ITEMS)); + break; + + case R.id.btnDownload: + final Context context = v.getContext(); + ProfileModel profileModel = feedModel.getProfileModel(); + final String username = profileModel != null ? profileModel.getUsername() : null; + + final ViewerPostModel[] sliderItems = feedModel.getSliderItems(); + + if (feedModel.getItemType() != MediaItemType.MEDIA_TYPE_SLIDER || sliderItems == null || sliderItems.length == 1) + Utils.batchDownload(context, username, DownloadMethod.DOWNLOAD_FEED, Collections.singletonList(feedModel)); + else { + final ArrayList postModels = new ArrayList<>(); + final DialogInterface.OnClickListener clickListener = (dialog, which) -> { + postModels.clear(); + + final boolean breakWhenFoundSelected = which == DialogInterface.BUTTON_POSITIVE; + + for (final ViewerPostModel sliderItem : sliderItems) { + if (sliderItem != null) { + if (!breakWhenFoundSelected) postModels.add(sliderItem); + else if (sliderItem.isSelected()) { + postModels.add(sliderItem); + break; + } + } + } + + // shows 0 items on first item of viewpager cause onPageSelected hasn't been called yet + if (breakWhenFoundSelected && postModels.size() == 0) + postModels.add(sliderItems[0]); + + if (postModels.size() > 0) + Utils.batchDownload(context, username, DownloadMethod.DOWNLOAD_FEED, postModels); + }; + + new AlertDialog.Builder(context).setTitle(R.string.post_viewer_download_dialog_title) + .setPositiveButton(R.string.post_viewer_download_current, clickListener) + .setNegativeButton(R.string.post_viewer_download_album, clickListener).show(); + } + break; + + case R.id.ivProfilePic: + if (mentionClickListener != null) { + profileModel = feedModel.getProfileModel(); + if (profileModel != null) + mentionClickListener.onClick(null, profileModel.getUsername(), false); + } + break; + } + } + } + } + }; + private final View.OnLongClickListener longClickListener = v -> { + final Object tag; + if (v instanceof RamboTextView && (tag = v.getTag()) instanceof FeedModel) + Utils.copyText(v.getContext(), ((FeedModel) tag).getPostCaption()); + return true; + }; + public SimpleExoPlayer pagerPlayer; + private final PlayerChangeListener playerChangeListener = (childPos, player) -> { + // todo + pagerPlayer = player; + }; + + public FeedAdapter(final Activity activity, final ArrayList FeedModels, final MentionClickListener mentionClickListener) { + this.activity = activity; + this.feedModels = FeedModels; + this.mentionClickListener = mentionClickListener; + this.layoutInflater = LayoutInflater.from(activity); + } + + @NonNull + @Override + public FeedItemViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) { + final View view; + if (viewType == MediaItemType.MEDIA_TYPE_VIDEO.ordinal()) + view = layoutInflater.inflate(R.layout.item_feed_video, parent, false); + else if (viewType == MediaItemType.MEDIA_TYPE_SLIDER.ordinal()) + view = layoutInflater.inflate(R.layout.item_feed_slider, parent, false); + else + view = layoutInflater.inflate(R.layout.item_feed, parent, false); + return new FeedItemViewHolder(view); + } + + @SuppressLint("SetTextI18n") + @Override + public void onBindViewHolder(@NonNull final FeedItemViewHolder viewHolder, final int position) { + final FeedModel feedModel = feedModels.get(position); + if (feedModel != null) { + final RequestManager glideRequestManager = Glide.with(viewHolder.itemView); + + feedModel.setPosition(position); + + viewHolder.viewPost.setTag(feedModel); + viewHolder.profilePic.setTag(feedModel); + viewHolder.btnDownload.setTag(feedModel); + viewHolder.viewerCaption.setTag(feedModel); + + final ProfileModel profileModel = feedModel.getProfileModel(); + if (profileModel != null) { + glideRequestManager.load(profileModel.getSdProfilePic()).into(viewHolder.profilePic); + viewHolder.username.setText(profileModel.getUsername()); + } + + viewHolder.viewPost.setOnClickListener(clickListener); + viewHolder.profilePic.setOnClickListener(clickListener); + viewHolder.btnDownload.setOnClickListener(clickListener); + + viewHolder.tvPostDate.setText(feedModel.getPostDate()); + + final long commentsCount = feedModel.getCommentsCount(); + viewHolder.commentsCount.setText(String.valueOf(commentsCount)); + + if (commentsCount <= 0) { + viewHolder.btnComments.setTag(null); + viewHolder.btnComments.setOnClickListener(null); + viewHolder.btnComments.setEnabled(false); + } else { + viewHolder.btnComments.setTag(feedModel); + viewHolder.btnComments.setOnClickListener(clickListener); + viewHolder.btnComments.setEnabled(true); + } + + final String thumbnailUrl = feedModel.getThumbnailUrl(); + final String displayUrl = feedModel.getDisplayUrl(); + CharSequence postCaption = feedModel.getPostCaption(); + + final boolean captionEmpty = Utils.isEmpty(postCaption); + + viewHolder.viewerCaption.setOnClickListener(clickListener); + viewHolder.viewerCaption.setOnLongClickListener(longClickListener); + viewHolder.viewerCaption.setVisibility(captionEmpty ? View.GONE : View.VISIBLE); + + if (!captionEmpty && Utils.hasMentions(postCaption)) { + postCaption = Utils.getMentionText(postCaption); + feedModel.setPostCaption(postCaption); + viewHolder.viewerCaption.setText(postCaption, TextView.BufferType.SPANNABLE); + viewHolder.viewerCaption.setMentionClickListener(mentionClickListener); + } else { + viewHolder.viewerCaption.setText(postCaption); + } + + expandCollapseTextView(viewHolder.viewerCaption, feedModel); + + final MediaItemType itemType = feedModel.getItemType(); + final View viewToChangeHeight; + + if (itemType == MediaItemType.MEDIA_TYPE_VIDEO) { + viewToChangeHeight = viewHolder.playerView; + + viewHolder.videoViewsParent.setVisibility(View.VISIBLE); + viewHolder.videoViews.setText(String.valueOf(feedModel.getViewCount())); + } else { + viewHolder.videoViewsParent.setVisibility(View.GONE); + viewHolder.btnMute.setVisibility(View.GONE); + + if (itemType == MediaItemType.MEDIA_TYPE_SLIDER) { + viewToChangeHeight = viewHolder.mediaList; + + final ViewerPostModel[] sliderItems = feedModel.getSliderItems(); + final int sliderItemLen = sliderItems != null ? sliderItems.length : 0; + + if (sliderItemLen > 0) { + viewHolder.mediaCounter.setText("1/" + sliderItemLen); + viewHolder.mediaList.setOffscreenPageLimit(Math.min(5, sliderItemLen)); + + final ViewPager.SimpleOnPageChangeListener simpleOnPageChangeListener = new ViewPager.SimpleOnPageChangeListener() { + private int prevPos = 0; + + @Override + public void onPageSelected(final int position) { + ViewerPostModel sliderItem = sliderItems[prevPos]; + if (sliderItem != null) sliderItem.setSelected(false); + sliderItem = sliderItems[position]; + if (sliderItem != null) sliderItem.setSelected(true); + + View childAt = viewHolder.mediaList.getChildAt(prevPos); + if (childAt instanceof PlayerView) { + pagerPlayer = (SimpleExoPlayer) ((PlayerView) childAt).getPlayer(); + if (pagerPlayer != null) pagerPlayer.setPlayWhenReady(false); + } + childAt = viewHolder.mediaList.getChildAt(position); + if (childAt instanceof PlayerView) { + pagerPlayer = (SimpleExoPlayer) ((PlayerView) childAt).getPlayer(); + if (pagerPlayer != null) pagerPlayer.setPlayWhenReady(true); + } + prevPos = position; + viewHolder.mediaCounter.setText((position + 1) + "/" + sliderItemLen); + } + }; + + //noinspection deprecation + viewHolder.mediaList.setOnPageChangeListener(simpleOnPageChangeListener); // cause add listeners might add to recycled holders + + final View.OnClickListener muteClickListener = v -> { + Player player = null; + if (v instanceof PlayerView) player = ((PlayerView) v).getPlayer(); + else if (v instanceof ImageView || v == viewHolder.btnMute) { + final int currentItem = viewHolder.mediaList.getCurrentItem(); + if (currentItem < viewHolder.mediaList.getChildCount()) { + final View childAt = viewHolder.mediaList.getChildAt(currentItem); + if (childAt instanceof PlayerView) player = ((PlayerView) childAt).getPlayer(); + } + + } else { + final Object tag = v.getTag(); + if (tag instanceof Player) player = (Player) tag; + } + + if (player instanceof SimpleExoPlayer) { + final SimpleExoPlayer exoPlayer = (SimpleExoPlayer) player; + final float intVol = exoPlayer.getVolume() == 0f ? 1f : 0f; + exoPlayer.setVolume(intVol); + viewHolder.btnMute.setImageResource(intVol == 0f ? R.drawable.vol : R.drawable.mute); + Utils.sessionVolumeFull = intVol == 1f; + } + }; + + viewHolder.btnMute.setOnClickListener(muteClickListener); + viewHolder.mediaList.setAdapter(new ChildMediaItemsAdapter(sliderItems, viewHolder.btnMute, muteClickListener, playerChangeListener)); + } + } else { + viewToChangeHeight = viewHolder.imageView; + String url = displayUrl; + if (Utils.isEmpty(url)) url = thumbnailUrl; + glideRequestManager.load(url).into(viewHolder.imageView); + } + } + + if (viewToChangeHeight != null) { + final ViewGroup.LayoutParams layoutParams = viewToChangeHeight.getLayoutParams(); + layoutParams.height = Utils.displayMetrics.widthPixels + 1; + viewToChangeHeight.setLayoutParams(layoutParams); + } + } + } + + @Override + public int getItemCount() { + return feedModels == null ? 0 : feedModels.size(); + } + + @Override + public int getItemViewType(final int position) { + if (feedModels != null) return feedModels.get(position).getItemType().ordinal(); + return MediaItemType.MEDIA_TYPE_IMAGE.ordinal(); + } + + /** + * expands or collapses {@link RamboTextView} [stg idek why i wrote this documentation] + * + * @param textView the {@link RamboTextView} view, to expand and collapse + * @param feedModel the {@link FeedModel} model to check wether model is collapsed to expanded + * + * @return true if expanded/collapsed, false if empty or text size is <= 255 chars + */ + public static boolean expandCollapseTextView(@NonNull final RamboTextView textView, @NonNull final FeedModel feedModel) { + final CharSequence caption = feedModel.getPostCaption(); + if (Utils.isEmpty(caption)) return false; + + final TextView.BufferType bufferType = caption instanceof Spanned ? TextView.BufferType.SPANNABLE : TextView.BufferType.NORMAL; + + if (!feedModel.isCaptionExpanded()) { + int i = Utils.indexOfChar(caption, '\r', 0); + if (i == -1) i = Utils.indexOfChar(caption, '\n', 0); + if (i == -1) i = 255; + + final int captionLen = caption.length(); + final int minTrim = Math.min(255, i); + if (captionLen <= minTrim) return false; + + final CharSequence mentionText = caption.subSequence(0, Math.min(captionLen, minTrim)); + final SpannableStringBuilder stringBuilder = new SpannableStringBuilder(mentionText).append(ellipsize); + final int spanLen = stringBuilder.length(); + + // fixed @mention...more merging into one span + final CommentMentionClickSpan[] spans = stringBuilder.getSpans(0, mentionText.length(), CommentMentionClickSpan.class); + if (spans != null) { + for (final CommentMentionClickSpan span : spans) { + final int spanStart = stringBuilder.getSpanStart(span); + stringBuilder.removeSpan(span); + stringBuilder.setSpan(span, spanStart, mentionText.length(), 0); + } + } + + stringBuilder.setSpan(new StyleSpan(Typeface.BOLD), spanLen - ellipsize.length(), spanLen, 0); + + textView.setText(stringBuilder, bufferType); + textView.setCaptionIsExpandable(true); + textView.setCaptionIsExpanded(true); + } else { + textView.setText(caption, bufferType); + textView.setCaptionIsExpanded(false); + } + return true; + } + + private interface PlayerChangeListener { + void playerChanged(final int childPos, final SimpleExoPlayer player); + } + + private static final class ChildMediaItemsAdapter extends PagerAdapter { + private final PlayerChangeListener playerChangeListener; + private final View.OnClickListener muteClickListener; + private final ViewerPostModel[] sliderItems; + private final View btnMute; + private SimpleExoPlayer player; + + private ChildMediaItemsAdapter(final ViewerPostModel[] sliderItems, final View btnMute, final View.OnClickListener muteClickListener, + final PlayerChangeListener playerChangeListener) { + this.muteClickListener = muteClickListener; + this.sliderItems = sliderItems; + this.btnMute = btnMute; + if (BuildConfig.DEBUG) this.playerChangeListener = playerChangeListener; + else this.playerChangeListener = null; + } + + @NonNull + @Override + public Object instantiateItem(@NonNull final ViewGroup container, final int position) { + if (BuildConfig.DEBUG) container.setBackgroundColor(0xFF_0a_c0_09); // todo remove + + final Context context = container.getContext(); + final ViewerPostModel sliderItem = sliderItems[position]; + + if (sliderItem.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO) { + if (btnMute != null) btnMute.setVisibility(View.VISIBLE); + final PlayerView playerView = new PlayerView(context); + + player = new SimpleExoPlayer.Builder(context).build(); + playerView.setPlayer(player); + + float vol = settingsHelper.getBoolean(Constants.MUTED_VIDEOS) ? 0f : 1f; + if (vol == 0f && Utils.sessionVolumeFull) vol = 1f; + player.setVolume(vol); + player.setPlayWhenReady(Utils.settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS)); + + final ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(new DefaultDataSourceFactory(context, "instagram")) + .createMediaSource(Uri.parse(sliderItem.getDisplayUrl())); + + player.setRepeatMode(Player.REPEAT_MODE_ALL); + player.prepare(mediaSource); + player.setVolume(vol); + + playerView.setTag(player); + playerView.setOnClickListener(muteClickListener); + + if (playerChangeListener != null) { + //todo + // playerChangeListener.playerChanged(position, player); + Log.d("AWAISKING_APP", "playerChangeListener: " + playerChangeListener); + } + + container.addView(playerView); + return playerView; + } else { + if (btnMute != null) btnMute.setVisibility(View.GONE); + + final PhotoView photoView = new PhotoView(context); + photoView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + Glide.with(context).load(sliderItem.getDisplayUrl()).into(photoView); + container.addView(photoView); + return photoView; + } + } + + @Override + public void destroyItem(@NonNull final ViewGroup container, final int position, @NonNull final Object object) { + final Player player = object instanceof PlayerView ? ((PlayerView) object).getPlayer() : this.player; + + if (player == this.player && this.player != null) { + this.player.stop(true); + this.player.release(); + } else if (player != null) { + player.stop(true); + player.release(); + } + + container.removeView((View) object); + } + + @Override + public int getCount() { + return sliderItems != null ? sliderItems.length : 0; + } + + @Override + public boolean isViewFromObject(@NonNull final View view, @NonNull final Object object) { + return view == object; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/FeedStoriesAdapter.java b/app/src/main/java/awais/instagrabber/adapters/FeedStoriesAdapter.java new file mode 100755 index 00000000..f28bfeb3 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/FeedStoriesAdapter.java @@ -0,0 +1,57 @@ +package awais.instagrabber.adapters; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; + +import awais.instagrabber.R; +import awais.instagrabber.adapters.viewholder.HighlightViewHolder; +import awais.instagrabber.models.FeedStoryModel; +import awais.instagrabber.models.ProfileModel; + +public final class FeedStoriesAdapter extends RecyclerView.Adapter { + private final View.OnClickListener clickListener; + private LayoutInflater layoutInflater; + private FeedStoryModel[] feedStoryModels; + + public FeedStoriesAdapter(final FeedStoryModel[] feedStoryModels, final View.OnClickListener clickListener) { + this.feedStoryModels = feedStoryModels; + this.clickListener = clickListener; + } + + @NonNull + @Override + public HighlightViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) { + if (layoutInflater == null) layoutInflater = LayoutInflater.from(parent.getContext()); + return new HighlightViewHolder(layoutInflater.inflate(R.layout.item_highlight, parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull final HighlightViewHolder holder, final int position) { + final FeedStoryModel feedStoryModel = feedStoryModels[position]; + if (feedStoryModel != null) { + holder.itemView.setTag(feedStoryModel); + holder.itemView.setOnClickListener(clickListener); + + final ProfileModel profileModel = feedStoryModel.getProfileModel(); + + holder.title.setText(profileModel.getUsername()); + Glide.with(layoutInflater.getContext()).load(profileModel.getSdProfilePic()).into(holder.icon); + } + } + + public void setData(final FeedStoryModel[] feedStoryModels) { + this.feedStoryModels = feedStoryModels; + notifyDataSetChanged(); + } + + @Override + public int getItemCount() { + return feedStoryModels == null ? 0 : feedStoryModels.length; + } +} diff --git a/app/src/main/java/awais/instagrabber/adapters/FollowAdapter.java b/app/src/main/java/awais/instagrabber/adapters/FollowAdapter.java new file mode 100755 index 00000000..7466022b --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/FollowAdapter.java @@ -0,0 +1,144 @@ +package awais.instagrabber.adapters; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Filter; +import android.widget.Filterable; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; + +import java.util.ArrayList; +import java.util.List; + +import awais.instagrabber.R; +import awais.instagrabber.adapters.viewholder.FollowsViewHolder; +import awais.instagrabber.interfaces.OnGroupClickListener; +import awais.instagrabber.models.FollowModel; +import awais.instagrabber.utils.Utils; +import thoughtbot.expandableadapter.ExpandableGroup; +import thoughtbot.expandableadapter.ExpandableList; +import thoughtbot.expandableadapter.ExpandableListPosition; +import thoughtbot.expandableadapter.GroupViewHolder; + +// thanks to ThoughtBot's ExpandableRecyclerViewAdapter +// https://github.com/thoughtbot/expandable-recycler-view +public final class FollowAdapter extends RecyclerView.Adapter implements OnGroupClickListener, Filterable { + private final Filter filter = new Filter() { + @Nullable + @Override + protected FilterResults performFiltering(final CharSequence filter) { + if (expandableList.groups != null) { + final boolean isFilterEmpty = Utils.isEmpty(filter); + final String query = isFilterEmpty ? null : filter.toString().toLowerCase(); + + for (int x = 0; x < expandableList.groups.size(); ++x) { + final ExpandableGroup expandableGroup = expandableList.groups.get(x); + final List items = expandableGroup.getItems(false); + final int itemCount = expandableGroup.getItemCount(false); + + for (int i = 0; i < itemCount; ++i) { + final FollowModel followModel = items.get(i); + + if (isFilterEmpty) followModel.setShown(true); + else followModel.setShown(Utils.hasKey(query, followModel.getUsername(), followModel.getFullName())); + } + } + } + return null; + } + + @Override + protected void publishResults(final CharSequence constraint, final FilterResults results) { + notifyDataSetChanged(); + } + }; + private final View.OnClickListener onClickListener; + private final LayoutInflater layoutInflater; + private final ExpandableList expandableList; + private final boolean hasManyGroups; + + public FollowAdapter(final Context context, final View.OnClickListener onClickListener, @NonNull final ArrayList groups) { + this.layoutInflater = LayoutInflater.from(context); + this.expandableList = new ExpandableList(groups); + this.onClickListener = onClickListener; + this.hasManyGroups = groups.size() > 1; + } + + @Override + public Filter getFilter() { + return filter; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) { + final boolean isGroup = hasManyGroups && viewType == ExpandableListPosition.GROUP; + + final View view = layoutInflater.inflate(isGroup ? R.layout.header_follow : R.layout.item_follow, parent, false); + + return isGroup ? new GroupViewHolder(view, this) : new FollowsViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position) { + final ExpandableListPosition listPos = expandableList.getUnflattenedPosition(position); + final ExpandableGroup group = expandableList.getExpandableGroup(listPos); + + if (hasManyGroups && listPos.type == ExpandableListPosition.GROUP) { + final GroupViewHolder gvh = (GroupViewHolder) holder; + gvh.setTitle(group.getTitle()); + gvh.toggle(isGroupExpanded(group)); + + } else { + final FollowModel model = group.getItems(true).get(hasManyGroups ? listPos.childPos : position); + + final FollowsViewHolder followHolder = (FollowsViewHolder) holder; + if (model != null) { + followHolder.itemView.setTag(model); + followHolder.itemView.setOnClickListener(onClickListener); + + followHolder.tvUsername.setText(model.getUsername()); + followHolder.tvFullName.setText(model.getFullName()); + + Glide.with(layoutInflater.getContext()).load(model.getProfilePicUrl()).into(followHolder.profileImage); + } + } + } + + @Override + public int getItemCount() { + return expandableList.getVisibleItemCount() - (hasManyGroups ? 0 : 1); + } + + @Override + public int getItemViewType(final int position) { + return !hasManyGroups ? 0 : expandableList.getUnflattenedPosition(position).type; + } + + @Override + public void toggleGroup(final int flatPos) { + final ExpandableListPosition listPosition = expandableList.getUnflattenedPosition(flatPos); + + final int groupPos = listPosition.groupPos; + final int positionStart = expandableList.getFlattenedGroupIndex(listPosition) + 1; + final int positionEnd = expandableList.groups.get(groupPos).getItemCount(true); + + final boolean isExpanded = expandableList.expandedGroupIndexes[groupPos]; + expandableList.expandedGroupIndexes[groupPos] = !isExpanded; + notifyItemChanged(positionStart - 1); + if (positionEnd > 0) { + if (isExpanded) notifyItemRangeRemoved(positionStart, positionEnd); + else notifyItemRangeInserted(positionStart, positionEnd); + } + } + + public boolean isGroupExpanded(final ExpandableGroup group) { + return expandableList.expandedGroupIndexes[expandableList.groups.indexOf(group)]; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/HighlightsAdapter.java b/app/src/main/java/awais/instagrabber/adapters/HighlightsAdapter.java new file mode 100755 index 00000000..af7460f7 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/HighlightsAdapter.java @@ -0,0 +1,53 @@ +package awais.instagrabber.adapters; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; + +import awais.instagrabber.R; +import awais.instagrabber.adapters.viewholder.HighlightViewHolder; +import awais.instagrabber.models.HighlightModel; + +public final class HighlightsAdapter extends RecyclerView.Adapter { + private final View.OnClickListener clickListener; + private LayoutInflater layoutInflater; + private HighlightModel[] highlightModels; + + public HighlightsAdapter(final HighlightModel[] highlightModels, final View.OnClickListener clickListener) { + this.highlightModels = highlightModels; + this.clickListener = clickListener; + } + + @NonNull + @Override + public HighlightViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) { + if (layoutInflater == null) layoutInflater = LayoutInflater.from(parent.getContext()); + return new HighlightViewHolder(layoutInflater.inflate(R.layout.item_highlight, parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull final HighlightViewHolder holder, final int position) { + final HighlightModel highlightModel = highlightModels[position]; + if (highlightModel != null) { + holder.itemView.setTag(highlightModel); + holder.itemView.setOnClickListener(clickListener); + holder.title.setText(highlightModel.getTitle()); + Glide.with(holder.itemView).load(highlightModel.getThumbnailUrl()).into(holder.icon); + } + } + + public void setData(final HighlightModel[] highlightModels) { + this.highlightModels = highlightModels; + notifyDataSetChanged(); + } + + @Override + public int getItemCount() { + return highlightModels == null ? 0 : highlightModels.length; + } +} diff --git a/app/src/main/java/awais/instagrabber/adapters/MessageItemsAdapter.java b/app/src/main/java/awais/instagrabber/adapters/MessageItemsAdapter.java new file mode 100755 index 00000000..043e15c4 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/MessageItemsAdapter.java @@ -0,0 +1,354 @@ +package awais.instagrabber.adapters; + +import android.content.Context; +import android.text.Spanned; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.text.HtmlCompat; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; + +import java.util.ArrayList; + +import awais.instagrabber.R; +import awais.instagrabber.adapters.viewholder.directmessages.TextMessageViewHolder; +import awais.instagrabber.interfaces.MentionClickListener; +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.models.direct_messages.DirectItemModel; +import awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemMediaModel; +import awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemRavenMediaModel; +import awais.instagrabber.models.enums.DirectItemType; +import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.models.enums.RavenExpiringMediaType; +import awais.instagrabber.models.enums.RavenMediaViewType; +import awais.instagrabber.utils.Utils; + +import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemLinkContext; +import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemLinkModel; +import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemReelShareModel; +import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemVoiceMediaModel; +import static awais.instagrabber.models.direct_messages.DirectItemModel.RavenExpiringMediaActionSummaryModel; + +public final class MessageItemsAdapter extends RecyclerView.Adapter { + private static final int MESSAGE_INCOMING = 69, MESSAGE_OUTGOING = 420; + private final ProfileModel myProfileHolder = new ProfileModel(false, false, null, null, null, null, null, null, null, 0, 0, 0); + private final ArrayList directItemModels; + private final ArrayList users; + private final View.OnClickListener onClickListener; + private final MentionClickListener mentionClickListener; + private final View.OnClickListener openProfileClickListener = v -> { + final Object tag = v.getTag(); + if (tag instanceof ProfileModel) { + // todo do profile stuff + final ProfileModel profileModel = (ProfileModel) tag; + Log.d("AWAISKING_APP", "--> " + profileModel); + } + }; + private final int itemMargin; + private DirectItemVoiceMediaModel prevVoiceModel; + private ImageView prevPlayIcon; + private final View.OnClickListener voicePlayClickListener = v -> { + final Object tag = v.getTag(); + if (v instanceof ViewGroup && tag instanceof DirectItemVoiceMediaModel) { + final ImageView playIcon = (ImageView) ((ViewGroup) v).getChildAt(0); + final DirectItemVoiceMediaModel voiceMediaModel = (DirectItemVoiceMediaModel) tag; + final boolean voicePlaying = voiceMediaModel.isPlaying(); + voiceMediaModel.setPlaying(!voicePlaying); + + if (voiceMediaModel == prevVoiceModel) { + // todo pause / resume + } else { + // todo release prev audio, start new voice + if (prevVoiceModel != null) prevVoiceModel.setPlaying(false); + if (prevPlayIcon != null) prevPlayIcon.setImageResource(android.R.drawable.ic_media_play); + } + + if (voicePlaying) { + playIcon.setImageResource(android.R.drawable.ic_media_play); + } else { + playIcon.setImageResource(android.R.drawable.ic_media_pause); + } + + prevVoiceModel = voiceMediaModel; + prevPlayIcon = playIcon; + } + }; + private Context context; + private LayoutInflater layoutInflater; + private String strDmYou; + + public MessageItemsAdapter(final ArrayList directItemModels, final ArrayList users, + final View.OnClickListener onClickListener, final MentionClickListener mentionClickListener) { + this.users = users; + this.directItemModels = directItemModels; + this.onClickListener = onClickListener; + this.mentionClickListener = mentionClickListener; + this.itemMargin = Utils.displayMetrics.widthPixels / 5; + } + + @NonNull + @Override + public TextMessageViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int type) { + if (context == null) context = parent.getContext(); + if (strDmYou == null) strDmYou = context.getString(R.string.direct_messages_you); + if (layoutInflater == null) layoutInflater = LayoutInflater.from(context); + return new TextMessageViewHolder(layoutInflater.inflate(R.layout.item_message_item, parent, false), + onClickListener, mentionClickListener); + } + + @Override + public void onBindViewHolder(@NonNull final TextMessageViewHolder holder, final int position) { + final DirectItemModel directItemModel = directItemModels.get(position); + holder.itemView.setTag(directItemModel); + + if (directItemModel != null) { + final DirectItemType itemType = directItemModel.getItemType(); + + final ProfileModel user = getUser(directItemModel.getUserId()); + final int type = user == myProfileHolder ? MESSAGE_OUTGOING : MESSAGE_INCOMING; + + final RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) holder.itemView.getLayoutParams(); + layoutParams.setMargins(type == MESSAGE_OUTGOING ? itemMargin : 0, 0, + type == MESSAGE_INCOMING ? itemMargin : 0, 0); + + holder.tvMessage.setVisibility(View.GONE); + holder.voiceMessageContainer.setVisibility(View.GONE); + holder.ivAnimatedMessage.setVisibility(View.GONE); + holder.linkMessageContainer.setVisibility(View.GONE); + + holder.mediaMessageContainer.setVisibility(View.GONE); + holder.mediaTypeIcon.setVisibility(View.GONE); + holder.mediaExpiredIcon.setVisibility(View.GONE); + + holder.profileMessageContainer.setVisibility(View.GONE); + holder.isVerified.setVisibility(View.GONE); + + holder.btnOpenProfile.setVisibility(View.GONE); + holder.btnOpenProfile.setOnClickListener(null); + holder.btnOpenProfile.setTag(null); + + CharSequence text = "?"; + if (user != null && user != myProfileHolder) text = user.getUsername(); + else if (user == myProfileHolder) text = strDmYou; + text = text + " - " + directItemModel.getDateTime(); + + holder.tvUsername.setText(text); + + holder.ivProfilePic.setVisibility(type == MESSAGE_INCOMING ? View.VISIBLE : View.GONE); + + final RequestManager glideRequestManager = Glide.with(holder.itemView); + + if (type == MESSAGE_INCOMING && user != null) + glideRequestManager.load(user.getSdProfilePic()).into(holder.ivProfilePic); + + DirectItemMediaModel mediaModel = directItemModel.getMediaModel(); + switch (itemType) { + case PLACEHOLDER: + case TEXT: + text = directItemModel.getText(); + text = Utils.getSpannableUrl(text.toString()); // for urls + if (Utils.hasMentions(text)) text = Utils.getMentionText(text); // for mentions + + if (text instanceof Spanned) holder.tvMessage.setText(text, TextView.BufferType.SPANNABLE); + else if (text == "") holder.tvMessage.setText(context.getText(R.string.dms_inbox_raven_message_unknown)); + else holder.tvMessage.setText(text); + + holder.tvMessage.setVisibility(View.VISIBLE); + break; + + case LINK: { + final DirectItemLinkModel link = directItemModel.getLinkModel(); + final DirectItemLinkContext linkContext = link.getLinkContext(); + + final String linkImageUrl = linkContext.getLinkImageUrl(); + if (!Utils.isEmpty(linkImageUrl)) { + glideRequestManager.load(linkImageUrl).into(holder.ivLinkPreview); + holder.tvLinkTitle.setText(linkContext.getLinkTitle()); + holder.tvLinkSummary.setText(linkContext.getLinkSummary()); + holder.ivLinkPreview.setVisibility(View.VISIBLE); + holder.linkMessageContainer.setVisibility(View.VISIBLE); + } + + holder.tvMessage.setText(Utils.getSpannableUrl(link.getText())); + holder.tvMessage.setVisibility(View.VISIBLE); + } + break; + + case MEDIA_SHARE: { + final ProfileModel modelUser = mediaModel.getUser(); + if (modelUser != null) { + holder.tvMessage.setText(context.getString(R.string.dms_inbox_media_shared_from, modelUser.getUsername())); + holder.tvMessage.setVisibility(View.VISIBLE); + } + } + case MEDIA: { + glideRequestManager.load(mediaModel.getThumbUrl()).into(holder.ivMediaPreview); + + final MediaItemType modelMediaType = mediaModel.getMediaType(); + holder.mediaTypeIcon.setVisibility(modelMediaType == MediaItemType.MEDIA_TYPE_VIDEO || + modelMediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE); + + holder.mediaMessageContainer.setVisibility(View.VISIBLE); + } + break; + + case RAVEN_MEDIA: { + final DirectItemRavenMediaModel ravenMediaModel = directItemModel.getRavenMediaModel(); + final RavenExpiringMediaActionSummaryModel mediaActionSummary = ravenMediaModel.getExpiringMediaActionSummary(); + + mediaModel = ravenMediaModel.getMedia(); + + final boolean isExpired = mediaModel == null || + Utils.isEmpty(mediaModel.getThumbUrl()) && mediaModel.getPk() < 1; + + holder.mediaExpiredIcon.setVisibility(isExpired ? View.VISIBLE : View.GONE); + + int textRes = R.string.dms_inbox_raven_media_unknown; + if (isExpired) textRes = R.string.dms_inbox_raven_media_expired; + + if (!isExpired && mediaActionSummary != null) { + final RavenExpiringMediaType expiringMediaType = mediaActionSummary.getType(); + + if (expiringMediaType == RavenExpiringMediaType.RAVEN_DELIVERED) + textRes = R.string.dms_inbox_raven_media_delivered; + else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SENT) + textRes = R.string.dms_inbox_raven_media_sent; + else if (expiringMediaType == RavenExpiringMediaType.RAVEN_OPENED) + textRes = R.string.dms_inbox_raven_media_opened; + else if (expiringMediaType == RavenExpiringMediaType.RAVEN_REPLAYED) + textRes = R.string.dms_inbox_raven_media_replayed; + else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SENDING) + textRes = R.string.dms_inbox_raven_media_sending; + else if (expiringMediaType == RavenExpiringMediaType.RAVEN_BLOCKED) + textRes = R.string.dms_inbox_raven_media_blocked; + else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SUGGESTED) + textRes = R.string.dms_inbox_raven_media_suggested; + else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SCREENSHOT) + textRes = R.string.dms_inbox_raven_media_screenshot; + else if (expiringMediaType == RavenExpiringMediaType.RAVEN_CANNOT_DELIVER) + textRes = R.string.dms_inbox_raven_media_cant_deliver; + + final RavenMediaViewType ravenMediaViewType = ravenMediaModel.getViewType(); + if (ravenMediaViewType == RavenMediaViewType.PERMANENT || ravenMediaViewType == RavenMediaViewType.REPLAYABLE) { + final MediaItemType mediaType = mediaModel.getMediaType(); + holder.mediaTypeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO || + mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE); + + glideRequestManager.load(mediaModel.getThumbUrl()).into(holder.ivMediaPreview); + holder.mediaMessageContainer.setVisibility(View.VISIBLE); + } + } + + holder.tvMessage.setText(context.getText(textRes)); + holder.tvMessage.setVisibility(View.VISIBLE); + } + break; + + case REEL_SHARE: { + final DirectItemReelShareModel reelShare = directItemModel.getReelShare(); + if (!Utils.isEmpty(text = reelShare.getText())) { + holder.tvMessage.setText(text); + holder.tvMessage.setVisibility(View.VISIBLE); + } + + final DirectItemMediaModel reelShareMedia = reelShare.getMedia(); + final MediaItemType mediaType = reelShareMedia.getMediaType(); + + Log.d("austin_debug", "media: " + reelShareMedia); + + holder.mediaTypeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO || + mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE); + + glideRequestManager.load(reelShareMedia.getThumbUrl()).into(holder.ivMediaPreview); + holder.mediaMessageContainer.setVisibility(View.VISIBLE); + } + break; + + case VOICE_MEDIA: { + final DirectItemVoiceMediaModel voiceMediaModel = directItemModel.getVoiceMediaModel(); + + if (voiceMediaModel != null) { + final int[] waveformData = voiceMediaModel.getWaveformData(); + if (waveformData != null) holder.waveformSeekBar.setSample(waveformData); + + final long durationMs = voiceMediaModel.getDurationMs(); + holder.tvVoiceDuration.setText(Utils.millisToString(durationMs)); + holder.waveformSeekBar.setProgress(voiceMediaModel.getProgress()); + holder.waveformSeekBar.setProgressChangeListener((waveformSeekBar, progress, fromUser) -> { + // todo progress audio player + voiceMediaModel.setProgress(progress); + if (fromUser) + holder.tvVoiceDuration.setText(Utils.millisToString(durationMs * progress / 100)); + }); + holder.btnPlayVoice.setTag(voiceMediaModel); + holder.btnPlayVoice.setOnClickListener(voicePlayClickListener); + } else { + holder.waveformSeekBar.setProgress(0); + } + + holder.voiceMessageContainer.setVisibility(View.VISIBLE); + } + break; + + case ANIMATED_MEDIA: { + glideRequestManager.asGif().load(directItemModel.getAnimatedMediaModel().getGifUrl()) + .into(holder.ivAnimatedMessage); + holder.ivAnimatedMessage.setVisibility(View.VISIBLE); + } + break; + + case PROFILE: { + final ProfileModel profileModel = directItemModel.getProfileModel(); + Glide.with(holder.ivMessageProfilePic).load(profileModel.getSdProfilePic()) + .into(holder.ivMessageProfilePic); + holder.btnOpenProfile.setTag(profileModel); + holder.btnOpenProfile.setOnClickListener(openProfileClickListener); + + holder.tvProfileName.setText(profileModel.getName()); + holder.tvProfileUsername.setText(profileModel.getUsername()); + holder.isVerified.setVisibility(profileModel.isVerified() ? View.VISIBLE : View.GONE); + + holder.btnOpenProfile.setVisibility(View.VISIBLE); + holder.profileMessageContainer.setVisibility(View.VISIBLE); + } + break; + + case VIDEO_CALL_EVENT: { + // todo add call event info + holder.tvMessage.setVisibility(View.VISIBLE); + holder.itemView.setBackgroundColor(0xFF_1F90E6); // blue bitch + } + break; + } + } + } + + @Override + public int getItemViewType(final int position) { + return directItemModels.get(position).getItemType().ordinal(); + } + + @Override + public int getItemCount() { + return directItemModels == null ? 0 : directItemModels.size(); + } + + @Nullable + private ProfileModel getUser(final long userId) { + if (users != null) { + for (final ProfileModel user : users) + if (Long.toString(userId).equals(user.getId())) return user; + return myProfileHolder; + } + return null; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/PostsAdapter.java b/app/src/main/java/awais/instagrabber/adapters/PostsAdapter.java new file mode 100755 index 00000000..4fb4598f --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/PostsAdapter.java @@ -0,0 +1,92 @@ +package awais.instagrabber.adapters; + +import android.graphics.drawable.Drawable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; + +import java.util.ArrayList; + +import awais.instagrabber.R; +import awais.instagrabber.adapters.viewholder.PostViewHolder; +import awais.instagrabber.models.PostModel; +import awais.instagrabber.models.enums.MediaItemType; + +public final class PostsAdapter extends RecyclerView.Adapter { + private final ArrayList postModels; + private final View.OnClickListener clickListener; + private final View.OnLongClickListener longClickListener; + private LayoutInflater layoutInflater; + public boolean isSelecting = false; + + public PostsAdapter(final ArrayList postModels, final View.OnClickListener clickListener, + final View.OnLongClickListener longClickListener) { + this.postModels = postModels; + this.clickListener = clickListener; + this.longClickListener = longClickListener; + } + + @NonNull + @Override + public PostViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) { + if (layoutInflater == null) layoutInflater = LayoutInflater.from(parent.getContext()); + return new PostViewHolder(layoutInflater.inflate(R.layout.item_post, parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull final PostViewHolder holder, final int position) { + final PostModel postModel = postModels.get(position); + if (postModel != null) { + postModel.setPosition(position); + + holder.itemView.setTag(postModel); + + holder.itemView.setOnClickListener(clickListener); + holder.itemView.setOnLongClickListener(longClickListener); + + final MediaItemType itemType = postModel.getItemType(); + final boolean isSlider = itemType == MediaItemType.MEDIA_TYPE_SLIDER; + + holder.isDownloaded.setVisibility(postModel.isDownloaded() ? View.VISIBLE : View.GONE); + + holder.typeIcon.setVisibility(itemType == MediaItemType.MEDIA_TYPE_VIDEO || isSlider ? View.VISIBLE : View.GONE); + holder.typeIcon.setImageResource(isSlider ? R.drawable.slider : R.drawable.video); + + holder.selectedView.setVisibility(postModel.isSelected() ? View.VISIBLE : View.GONE); + holder.progressView.setVisibility(View.VISIBLE); + + final RequestManager glideRequestManager = Glide.with(holder.postImage); + + glideRequestManager.load(postModel.getThumbnailUrl()).listener(new RequestListener() { + @Override + public boolean onResourceReady(final Drawable resource, final Object model, final Target target, final DataSource dataSource, final boolean isFirstResource) { + holder.progressView.setVisibility(View.GONE); + return false; + } + + @Override + public boolean onLoadFailed(@Nullable final GlideException e, final Object model, final Target target, final boolean isFirstResource) { + holder.progressView.setVisibility(View.GONE); + glideRequestManager.load(postModel.getDisplayUrl()).into(holder.postImage); + return false; + } + }).into(holder.postImage); + } + } + + @Override + public int getItemCount() { + return postModels == null ? 0 : postModels.size(); + } +} diff --git a/app/src/main/java/awais/instagrabber/adapters/PostsMediaAdapter.java b/app/src/main/java/awais/instagrabber/adapters/PostsMediaAdapter.java new file mode 100755 index 00000000..f2786b6b --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/PostsMediaAdapter.java @@ -0,0 +1,68 @@ +package awais.instagrabber.adapters; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; + +import awais.instagrabber.R; +import awais.instagrabber.adapters.viewholder.PostMediaViewHolder; +import awais.instagrabber.models.BasePostModel; +import awais.instagrabber.models.ViewerPostModel; + +public final class PostsMediaAdapter extends RecyclerView.Adapter { + private final View.OnClickListener clickListener; + private LayoutInflater layoutInflater; + private ViewerPostModel[] postModels; + + public PostsMediaAdapter(final ViewerPostModel[] postModels, final View.OnClickListener clickListener) { + this.postModels = postModels; + this.clickListener = clickListener; + } + + @NonNull + @Override + public PostMediaViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) { + if (layoutInflater == null) layoutInflater = LayoutInflater.from(parent.getContext()); + return new PostMediaViewHolder(layoutInflater.inflate(R.layout.item_child_post, parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull final PostMediaViewHolder holder, final int position) { + final ViewerPostModel postModel = postModels[position]; + if (postModel != null) { + postModel.setPosition(position); + + holder.itemView.setTag(postModel); + holder.itemView.setOnClickListener(clickListener); + + holder.selectedView.setVisibility(postModel.isCurrentSlide() ? View.VISIBLE : View.GONE); + + holder.isDownloaded.setVisibility(postModel.isDownloaded() ? View.VISIBLE : View.GONE); + + Glide.with(layoutInflater.getContext()).load(postModel.getSliderDisplayUrl()).into(holder.icon); + } + } + + public void setData(final ViewerPostModel[] postModels) { + this.postModels = postModels; + notifyDataSetChanged(); + } + + public ViewerPostModel getItemAt(final int position) { + return postModels == null ? null : postModels[position]; + } + + @Override + public int getItemCount() { + return postModels == null ? 0 : postModels.length; + } + + public BasePostModel[] getPostModels() { + return postModels; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/SimpleAdapter.java b/app/src/main/java/awais/instagrabber/adapters/SimpleAdapter.java new file mode 100755 index 00000000..bfdbd7b5 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/SimpleAdapter.java @@ -0,0 +1,75 @@ +package awais.instagrabber.adapters; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.List; + +import awais.instagrabber.R; +import awais.instagrabber.utils.DataBox; + +public final class SimpleAdapter extends RecyclerView.Adapter { + private List items; + private final LayoutInflater layoutInflater; + private final View.OnClickListener onClickListener; + private final View.OnLongClickListener longClickListener; + + public SimpleAdapter(final Context context, final List items, final View.OnClickListener onClickListener) { + this(context, items, onClickListener, null); + } + + public SimpleAdapter(final Context context, final List items, final View.OnClickListener onClickListener, + final View.OnLongClickListener longClickListener) { + this.layoutInflater = LayoutInflater.from(context); + this.items = items; + this.onClickListener = onClickListener; + this.longClickListener = longClickListener; + } + + public void setItems(final List items) { + this.items = items; + notifyDataSetChanged(); + } + + @NonNull + @Override + public SimpleViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) { + return new SimpleViewHolder(layoutInflater. + inflate(R.layout.item_dir_list, parent, false), onClickListener, longClickListener); + } + + @Override + public void onBindViewHolder(@NonNull final SimpleViewHolder holder, final int position) { + final T item = items.get(position); + holder.itemView.setTag(item); + holder.text.setText(item.toString()); + if (item instanceof DataBox.CookieModel && ((DataBox.CookieModel) item).isSelected() || + item instanceof String && ((String) item).toLowerCase().endsWith(".zaai")) + holder.itemView.setBackgroundColor(0xF0_125687); + else + holder.itemView.setBackground(null); + } + + @Override + public int getItemCount() { + return items != null ? items.size() : 0; + } + + static final class SimpleViewHolder extends RecyclerView.ViewHolder { + private final TextView text; + + private SimpleViewHolder(@NonNull final View itemView, final View.OnClickListener onClickListener, + final View.OnLongClickListener longClickListener) { + super(itemView); + text = itemView.findViewById(android.R.id.text1); + itemView.setOnClickListener(onClickListener); + if (longClickListener != null) itemView.setOnLongClickListener(longClickListener); + } + } +} diff --git a/app/src/main/java/awais/instagrabber/adapters/StoriesAdapter.java b/app/src/main/java/awais/instagrabber/adapters/StoriesAdapter.java new file mode 100755 index 00000000..411fb98e --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/StoriesAdapter.java @@ -0,0 +1,84 @@ +package awais.instagrabber.adapters; + +import android.content.Context; +import android.content.res.Resources; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; + +import awais.instagrabber.R; +import awais.instagrabber.models.StoryModel; + +public final class StoriesAdapter extends RecyclerView.Adapter { + private final View.OnClickListener clickListener; + private LayoutInflater layoutInflater; + private StoryModel[] storyModels; + private Resources resources; + private int width, height; + + public StoriesAdapter(final StoryModel[] storyModels, final View.OnClickListener clickListener) { + this.storyModels = storyModels; + this.clickListener = clickListener; + } + + @NonNull + @Override + public StoryViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) { + final Context context = parent.getContext(); + if (layoutInflater == null) layoutInflater = LayoutInflater.from(context); + if (resources == null) resources = context.getResources(); + + height = Math.round(resources.getDimension(R.dimen.story_item_height)); + width = Math.round(resources.getDimension(R.dimen.story_item_width)); + + return new StoryViewHolder(layoutInflater.inflate(R.layout.item_story, parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull final StoryViewHolder holder, final int position) { + final StoryModel storyModel = storyModels[position]; + if (storyModel != null) { + storyModel.setPosition(position); + + holder.itemView.setTag(storyModel); + holder.itemView.setOnClickListener(clickListener); + + holder.selectedView.setVisibility(storyModel.isCurrentSlide() ? View.VISIBLE : View.GONE); + + Glide.with(holder.itemView).load(storyModel.getStoryUrl()) + .apply(new RequestOptions().override(width, height)) + .into(holder.icon); + } + } + + public void setData(final StoryModel[] storyModels) { + this.storyModels = storyModels; + notifyDataSetChanged(); + } + + public StoryModel getItemAt(final int position) { + return storyModels == null ? null : storyModels[position]; + } + + @Override + public int getItemCount() { + return storyModels == null ? 0 : storyModels.length; + } + + public final static class StoryViewHolder extends RecyclerView.ViewHolder { + public final ImageView icon, selectedView; + + public StoryViewHolder(@NonNull final View itemView) { + super(itemView); + selectedView = itemView.findViewById(R.id.selectedView); + icon = itemView.findViewById(R.id.icon); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/SuggestionsAdapter.java b/app/src/main/java/awais/instagrabber/adapters/SuggestionsAdapter.java new file mode 100755 index 00000000..601bc639 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/SuggestionsAdapter.java @@ -0,0 +1,60 @@ +package awais.instagrabber.adapters; + +import android.content.Context; +import android.database.Cursor; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.cursoradapter.widget.CursorAdapter; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.request.RequestOptions; + +import awais.instagrabber.R; + +public final class SuggestionsAdapter extends CursorAdapter { + private final LayoutInflater layoutInflater; + private final View.OnClickListener onClickListener; + private final RequestManager glideRequestManager; + + public SuggestionsAdapter(final Context context, final View.OnClickListener onClickListener) { + super(context, null, FLAG_REGISTER_CONTENT_OBSERVER); + this.glideRequestManager = Glide.with(context); + this.layoutInflater = LayoutInflater.from(context); + this.onClickListener = onClickListener; + } + + @Override + public View newView(final Context context, final Cursor cursor, final ViewGroup parent) { + return layoutInflater.inflate(R.layout.item_suggestion, parent, false); + } + + @Override + public void bindView(@NonNull final View view, final Context context, @NonNull final Cursor cursor) { + // i, username, fullname, type, picUrl, verified + // 0, 1 , 2 , 3 , 4 , 5 + + final String fullname = cursor.getString(2); + String username = cursor.getString(1); + final String picUrl = cursor.getString(4); + final boolean verified = cursor.getString(5).charAt(0) == 't'; + + if ("TYPE_HASHTAG".equals(cursor.getString(3))) username = '#' + username; + + view.setOnClickListener(onClickListener); + view.setTag(username); + + view.findViewById(R.id.isVerified).setVisibility(verified ? View.VISIBLE : View.GONE); + + ((TextView) view.findViewById(R.id.tvUsername)).setText(username); + ((TextView) view.findViewById(R.id.tvFullName)).setText(fullname); + + glideRequestManager.applyDefaultRequestOptions(new RequestOptions().skipMemoryCache(true)) + .load(picUrl).into((ImageView) view.findViewById(R.id.ivProfilePic)); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/CommentViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/CommentViewHolder.java new file mode 100755 index 00000000..08476443 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/CommentViewHolder.java @@ -0,0 +1,85 @@ +package awais.instagrabber.adapters.viewholder; + +import android.text.Spannable; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import awais.instagrabber.R; +import awais.instagrabber.adapters.CommentsAdapter; +import awais.instagrabber.customviews.RamboTextView; +import awais.instagrabber.interfaces.MentionClickListener; +import awais.instagrabber.models.CommentModel; + +public final class CommentViewHolder extends RecyclerView.ViewHolder { + private final MentionClickListener mentionClickListener; + private final RecyclerView rvChildComments; + private final ImageView ivProfilePic; + private final TextView tvUsername, tvDate, tvComment, tvLikes; + private final View container; + + public CommentViewHolder(@NonNull final View itemView, final View.OnClickListener onClickListener, final MentionClickListener mentionClickListener) { + super(itemView); + + container = itemView.findViewById(R.id.container); + if (onClickListener != null) container.setOnClickListener(onClickListener); + + this.mentionClickListener = mentionClickListener; + + ivProfilePic = itemView.findViewById(R.id.ivProfilePic); + tvUsername = itemView.findViewById(R.id.tvUsername); + tvDate = itemView.findViewById(R.id.tvDate); + tvLikes = itemView.findViewById(R.id.tvLikes); + tvComment = itemView.findViewById(R.id.tvComment); + + tvUsername.setSelected(true); + tvDate.setSelected(true); + + rvChildComments = itemView.findViewById(R.id.rvChildComments); + } + + public final ImageView getProfilePicView() { + return ivProfilePic; + } + + public final boolean isParent() { + return rvChildComments != null; + } + + public final void setCommentModel(final CommentModel commentModel) { + if (container != null) container.setTag(commentModel); + } + + public final void setUsername(final String username) { + if (tvUsername != null) tvUsername.setText(username); + } + + public final void setDate(final String date) { + if (tvDate != null) tvDate.setText(date); + } + + public final void setLikes(final String likes) { + if (tvLikes != null) tvLikes.setText(likes); + } + + public final void setCommment(final CharSequence commment) { + if (tvComment != null) { + tvComment.setText(commment, commment instanceof Spannable ? TextView.BufferType.SPANNABLE : TextView.BufferType.NORMAL); + ((RamboTextView) tvComment).setMentionClickListener(mentionClickListener); + } + } + + public final void setChildAdapter(final CommentsAdapter adapter) { + if (isParent()) { + rvChildComments.setAdapter(adapter); + rvChildComments.setVisibility(View.VISIBLE); + } + } + + public final void hideChildComments() { + if (isParent()) rvChildComments.setVisibility(View.GONE); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/DirectMessageViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/DirectMessageViewHolder.java new file mode 100755 index 00000000..c7cdddb4 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/DirectMessageViewHolder.java @@ -0,0 +1,43 @@ +package awais.instagrabber.adapters.viewholder; + +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import awais.instagrabber.R; + +public final class DirectMessageViewHolder extends RecyclerView.ViewHolder { + public final LinearLayout multipleProfilePicsContainer; + public final ImageView[] multipleProfilePics; + public final ImageView ivProfilePic, notTextType; + public final TextView tvUsername, tvDate, tvMessage; + + public DirectMessageViewHolder(@NonNull final View itemView, final View.OnClickListener clickListener) { + super(itemView); + + if (clickListener != null) itemView.setOnClickListener(clickListener); + + itemView.findViewById(R.id.tvLikes).setVisibility(View.GONE); + + tvDate = itemView.findViewById(R.id.tvDate); + tvMessage = itemView.findViewById(R.id.tvComment); + tvUsername = itemView.findViewById(R.id.tvUsername); + notTextType = itemView.findViewById(R.id.notTextType); + ivProfilePic = itemView.findViewById(R.id.ivProfilePic); + + multipleProfilePicsContainer = itemView.findViewById(R.id.container); + final LinearLayout containerChild = (LinearLayout) multipleProfilePicsContainer.getChildAt(1); + multipleProfilePics = new ImageView[]{ + (ImageView) multipleProfilePicsContainer.getChildAt(0), + (ImageView) containerChild.getChildAt(0), + (ImageView) containerChild.getChildAt(1) + }; + + tvDate.setSelected(true); + tvUsername.setSelected(true); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/DiscoverViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/DiscoverViewHolder.java new file mode 100755 index 00000000..6795ceb6 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/DiscoverViewHolder.java @@ -0,0 +1,22 @@ +package awais.instagrabber.adapters.viewholder; + +import android.view.View; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import awais.instagrabber.R; + +public final class DiscoverViewHolder extends RecyclerView.ViewHolder { + public final ImageView postImage, typeIcon; + public final View selectedView, progressView; + + public DiscoverViewHolder(@NonNull final View itemView) { + super(itemView); + typeIcon = itemView.findViewById(R.id.typeIcon); + postImage = itemView.findViewById(R.id.postImage); + selectedView = itemView.findViewById(R.id.selectedView); + progressView = itemView.findViewById(R.id.progressView); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/FeedItemViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/FeedItemViewHolder.java new file mode 100755 index 00000000..96aafd11 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/FeedItemViewHolder.java @@ -0,0 +1,52 @@ +package awais.instagrabber.adapters.viewholder; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager.widget.ViewPager; + +import com.github.chrisbanes.photoview.PhotoView; +import com.google.android.exoplayer2.ui.PlayerView; + +import awais.instagrabber.R; +import awais.instagrabber.customviews.RamboTextView; + +public final class FeedItemViewHolder extends RecyclerView.ViewHolder { + public final ImageView profilePic, btnMute, btnDownload; + public final TextView username, commentsCount, videoViews, mediaCounter, tvPostDate; + public final RamboTextView viewerCaption; + public final View btnComments, videoViewsParent, viewPost; + public final ViewPager mediaList; + public final PhotoView imageView; + public final PlayerView playerView; + + public FeedItemViewHolder(@NonNull final View itemView) { + super(itemView); + + // common + viewerCaption = itemView.findViewById(R.id.viewerCaption); + btnDownload = itemView.findViewById(R.id.btnDownload); + btnComments = itemView.findViewById(R.id.btnComments); + profilePic = itemView.findViewById(R.id.ivProfilePic); + tvPostDate = itemView.findViewById(R.id.tvPostDate); + viewPost = itemView.findViewById(R.id.viewStoryPost); + username = itemView.findViewById(R.id.title); + + // video view + btnMute = itemView.findViewById(R.id.btnMute); + videoViews = itemView.findViewById(R.id.tvVideoViews); + commentsCount = btnComments.findViewById(R.id.commentsCount); + videoViewsParent = videoViews != null ? (View) videoViews.getParent() : null; + + // slider view + mediaCounter = itemView.findViewById(R.id.mediaCounter); + + // different types + mediaList = itemView.findViewById(R.id.media_list); + imageView = itemView.findViewById(R.id.imageViewer); + playerView = itemView.findViewById(R.id.playerView); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/FollowsViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/FollowsViewHolder.java new file mode 100755 index 00000000..fb52eac1 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/FollowsViewHolder.java @@ -0,0 +1,22 @@ +package awais.instagrabber.adapters.viewholder; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import awais.instagrabber.R; + +public final class FollowsViewHolder extends RecyclerView.ViewHolder { + public final ImageView profileImage; + public final TextView tvFullName, tvUsername; + + public FollowsViewHolder(@NonNull final View itemView) { + super(itemView); + profileImage = itemView.findViewById(R.id.ivProfilePic); + tvFullName = itemView.findViewById(R.id.tvFullName); + tvUsername = itemView.findViewById(R.id.tvUsername); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/HighlightViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/HighlightViewHolder.java new file mode 100755 index 00000000..1d1654ff --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/HighlightViewHolder.java @@ -0,0 +1,21 @@ +package awais.instagrabber.adapters.viewholder; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import awais.instagrabber.R; + +public final class HighlightViewHolder extends RecyclerView.ViewHolder { + public final ImageView icon; + public final TextView title; + + public HighlightViewHolder(@NonNull final View itemView) { + super(itemView); + icon = itemView.findViewById(R.id.icon); + title = itemView.findViewById(R.id.title); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/PostMediaViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/PostMediaViewHolder.java new file mode 100755 index 00000000..65d115bd --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/PostMediaViewHolder.java @@ -0,0 +1,20 @@ +package awais.instagrabber.adapters.viewholder; + +import android.view.View; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import awais.instagrabber.R; + +public final class PostMediaViewHolder extends RecyclerView.ViewHolder { + public final ImageView icon, isDownloaded, selectedView; + + public PostMediaViewHolder(@NonNull final View itemView) { + super(itemView); + selectedView = itemView.findViewById(R.id.selectedView); + isDownloaded = itemView.findViewById(R.id.isDownloaded); + icon = itemView.findViewById(R.id.icon); + } +} diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/PostViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/PostViewHolder.java new file mode 100755 index 00000000..f76778b8 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/PostViewHolder.java @@ -0,0 +1,23 @@ +package awais.instagrabber.adapters.viewholder; + +import android.view.View; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import awais.instagrabber.R; + +public final class PostViewHolder extends RecyclerView.ViewHolder { + public final ImageView postImage, typeIcon; + public final View selectedView, progressView, isDownloaded; + + public PostViewHolder(@NonNull final View itemView) { + super(itemView); + typeIcon = itemView.findViewById(R.id.typeIcon); + postImage = itemView.findViewById(R.id.postImage); + isDownloaded = itemView.findViewById(R.id.isDownloaded); + selectedView = itemView.findViewById(R.id.selectedView); + progressView = itemView.findViewById(R.id.progressView); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/TextMessageViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/TextMessageViewHolder.java new file mode 100755 index 00000000..3e1bed67 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/TextMessageViewHolder.java @@ -0,0 +1,91 @@ +package awais.instagrabber.adapters.viewholder.directmessages; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.RecyclerView; + +import awais.instagrabber.R; +import awais.instagrabber.customviews.RamboTextView; +import awais.instagrabber.customviews.masoudss_waveform.WaveformSeekBar; +import awais.instagrabber.interfaces.MentionClickListener; + +public final class TextMessageViewHolder extends RecyclerView.ViewHolder { + public final CardView rootCardView; + public final TextView tvUsername; + public final ImageView ivProfilePic; + // text message + public final RamboTextView tvMessage; + // expired message icon + public final View mediaExpiredIcon; + // media message + public final View mediaMessageContainer; + public final ImageView ivMediaPreview, mediaTypeIcon; + // profile messag + public final View profileMessageContainer, isVerified, btnOpenProfile; + public final TextView tvProfileUsername, tvProfileName; + public final ImageView ivMessageProfilePic; + // animated message + public final ImageView ivAnimatedMessage; + // link message + public final View linkMessageContainer; + public final ImageView ivLinkPreview; + public final TextView tvLinkTitle, tvLinkSummary; + // voice message + public final View voiceMessageContainer, btnPlayVoice; + public final WaveformSeekBar waveformSeekBar; + public final TextView tvVoiceDuration; + + public TextMessageViewHolder(@NonNull final View itemView, final View.OnClickListener clickListener, + final MentionClickListener mentionClickListener) { + super(itemView); + + if (clickListener != null) itemView.setOnClickListener(clickListener); + + tvUsername = itemView.findViewById(R.id.tvUsername); + ivProfilePic = itemView.findViewById(R.id.ivProfilePic); + + // text message + tvMessage = itemView.findViewById(R.id.tvMessage); + tvMessage.setCaptionIsExpandable(true); + tvMessage.setCaptionIsExpanded(true); + if (mentionClickListener != null) tvMessage.setMentionClickListener(mentionClickListener); + + // root view + rootCardView = (CardView) tvMessage.getParent().getParent(); + + // expired message icon + mediaExpiredIcon = itemView.findViewById(R.id.mediaExpiredIcon); + + // media message + ivMediaPreview = itemView.findViewById(R.id.ivMediaPreview); + mediaMessageContainer = (View) ivMediaPreview.getParent(); + mediaTypeIcon = mediaMessageContainer.findViewById(R.id.typeIcon); + + // profile message + btnOpenProfile = itemView.findViewById(R.id.btnInfo); + ivMessageProfilePic = itemView.findViewById(R.id.profileInfo); + profileMessageContainer = (View) ivMessageProfilePic.getParent(); + isVerified = profileMessageContainer.findViewById(R.id.isVerified); + tvProfileName = profileMessageContainer.findViewById(R.id.tvFullName); + tvProfileUsername = profileMessageContainer.findViewById(R.id.profileInfoText); + + // animated message + ivAnimatedMessage = itemView.findViewById(R.id.ivAnimatedMessage); + + // link message + ivLinkPreview = itemView.findViewById(R.id.ivLinkPreview); + linkMessageContainer = (View) ivLinkPreview.getParent(); + tvLinkTitle = linkMessageContainer.findViewById(R.id.tvLinkTitle); + tvLinkSummary = linkMessageContainer.findViewById(R.id.tvLinkSummary); + + // voice message + waveformSeekBar = itemView.findViewById(R.id.waveformSeekBar); + voiceMessageContainer = (View) waveformSeekBar.getParent(); + btnPlayVoice = voiceMessageContainer.findViewById(R.id.btnPlayVoice); + tvVoiceDuration = voiceMessageContainer.findViewById(R.id.tvVoiceDuration); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/asyncs/CommentsFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/CommentsFetcher.java new file mode 100755 index 00000000..2ac012ba --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/CommentsFetcher.java @@ -0,0 +1,265 @@ +package awais.instagrabber.asyncs; + +import android.os.AsyncTask; +import android.util.Log; +import android.util.Pair; + +import androidx.annotation.NonNull; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.CommentModel; +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; +import awaisomereport.LogCollector; + +import static awais.instagrabber.utils.Utils.logCollector; + +public final class CommentsFetcher extends AsyncTask { + private final String shortCode; + private final FetchListener fetchListener; + + /* + * i fucking spent the whole day on this and fixing all the fucking problems in this class. + * DO NO FUCK WITH THIS CODE! + * -AWAiS (The Badak) @the.badak + */ + public CommentsFetcher(final String shortCode, final FetchListener fetchListener) { + this.shortCode = shortCode; + this.fetchListener = fetchListener; + } + + @NonNull + @Override + protected CommentModel[] doInBackground(final Void... voids) { + /* + "https://www.instagram.com/graphql/query/?query_hash=97b41c52301f77ce508f55e66d17620e&variables=" + "{\"shortcode\":\"" + shortcode + "\",\"first\":50,\"after\":\"" + endCursor + "\"}"; + + 97b41c52301f77ce508f55e66d17620e -> for comments + 51fdd02b67508306ad4484ff574a0b62 -> for child comments + + https://www.instagram.com/graphql/query/?query_hash=51fdd02b67508306ad4484ff574a0b62&variables={"comment_id":"18100041898085322","first":50,"after":""} + */ + final ArrayList commentModels = getParentComments(); + + for (final CommentModel commentModel : commentModels) { + final CommentModel[] childCommentModels = commentModel.getChildCommentModels(); + if (childCommentModels != null) { + final int childCommentsLen = childCommentModels.length; + + final CommentModel lastChild = childCommentModels[childCommentsLen - 1]; + if (lastChild != null && lastChild.hasNextPage() && !Utils.isEmpty(lastChild.getEndCursor())) { + final CommentModel[] remoteChildComments = getChildComments(commentModel.getId()); + commentModel.setChildCommentModels(remoteChildComments); + lastChild.setPageCursor(false, null); + } + } + } + + return commentModels.toArray(new CommentModel[0]); + } + + @Override + protected void onPreExecute() { + if (fetchListener != null) fetchListener.doBefore(); + } + + @Override + protected void onPostExecute(final CommentModel[] result) { + if (fetchListener != null) fetchListener.onResult(result); + } + + @NonNull + private synchronized CommentModel[] getChildComments(final String commentId) { + final ArrayList commentModels = new ArrayList<>(); + + String endCursor = ""; + while (endCursor != null) { + final String url = "https://www.instagram.com/graphql/query/?query_hash=51fdd02b67508306ad4484ff574a0b62&variables=" + + "{\"comment_id\":\"" + commentId + "\",\"first\":50,\"after\":\"" + endCursor + "\"}"; + + try { + final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setUseCaches(false); + conn.connect(); + + if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) break; + else { + final JSONObject data = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("data") + .getJSONObject("comment").getJSONObject("edge_threaded_comments"); + + final JSONObject pageInfo = data.getJSONObject("page_info"); + endCursor = pageInfo.getString("end_cursor"); + if (Utils.isEmpty(endCursor)) endCursor = null; + + final JSONArray childComments = data.optJSONArray("edges"); + if (childComments != null) { + final int length = childComments.length(); + for (int i = 0; i < length; ++i) { + final JSONObject childComment = childComments.getJSONObject(i).optJSONObject("node"); + + if (childComment != null) { + final JSONObject owner = childComment.getJSONObject("owner"); + final ProfileModel profileModel = new ProfileModel(false, + false, + owner.getString(Constants.EXTRAS_ID), + owner.getString(Constants.EXTRAS_USERNAME), + null, null, null, + owner.getString("profile_pic_url"), + null, 0, 0, 0); + + final JSONObject likedBy = childComment.optJSONObject("edge_liked_by"); + + commentModels.add(new CommentModel(childComment.getString(Constants.EXTRAS_ID), + childComment.getString("text"), + childComment.getLong("created_at"), + likedBy != null ? likedBy.optLong("count", 0) : 0, + profileModel)); + } + } + } + } + + conn.disconnect(); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.ASYNC_COMMENTS_FETCHER, "getChildComments", + new Pair<>("commentModels.size", commentModels.size())); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + break; + } + } + + return commentModels.toArray(new CommentModel[0]); + } + + @NonNull + private synchronized ArrayList getParentComments() { + final ArrayList commentModelsList = new ArrayList<>(); + + String endCursor = ""; + while (endCursor != null) { + final String url = "https://www.instagram.com/graphql/query/?query_hash=97b41c52301f77ce508f55e66d17620e&variables=" + + "{\"shortcode\":\"" + shortCode + "\",\"first\":50,\"after\":\"" + endCursor + "\"}"; + + try { + final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setUseCaches(false); + conn.connect(); + + if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) break; + else { + final JSONObject parentComments = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("data") + .getJSONObject("shortcode_media").getJSONObject("edge_media_to_parent_comment"); + + final JSONObject pageInfo = parentComments.getJSONObject("page_info"); + endCursor = pageInfo.optString("end_cursor"); + if (Utils.isEmpty(endCursor)) endCursor = null; + + // final boolean containsToken = endCursor.contains("bifilter_token"); + // if (!Utils.isEmpty(endCursor) && (containsToken || endCursor.contains("cached_comments_cursor"))) { + // final JSONObject endCursorObject = new JSONObject(endCursor); + // endCursor = endCursorObject.optString("cached_comments_cursor"); + // + // if (!Utils.isEmpty(endCursor)) + // endCursor = "{\\\"cached_comments_cursor\\\": \\\"" + endCursor + "\\\", "; + // else + // endCursor = "{"; + // + // endCursor = endCursor + "\\\"bifilter_token\\\": \\\"" + endCursorObject.getString("bifilter_token") + "\\\"}"; + // } + // else if (containsToken) endCursor = null; + + final JSONArray comments = parentComments.getJSONArray("edges"); + final int commentsLen = comments.length(); + final CommentModel[] commentModels = new CommentModel[commentsLen]; + + for (int i = 0; i < commentsLen; ++i) { + final JSONObject comment = comments.getJSONObject(i).getJSONObject("node"); + + final JSONObject owner = comment.getJSONObject("owner"); + final ProfileModel profileModel = new ProfileModel(false, + owner.optBoolean("is_verified"), + owner.getString(Constants.EXTRAS_ID), + owner.getString(Constants.EXTRAS_USERNAME), + null, null, null, + owner.getString("profile_pic_url"), + null, 0, 0, 0); + + final JSONObject likedBy = comment.optJSONObject("edge_liked_by"); + final String commentId = comment.getString(Constants.EXTRAS_ID); + commentModels[i] = new CommentModel(commentId, + comment.getString("text"), + comment.getLong("created_at"), + likedBy != null ? likedBy.optLong("count", 0) : 0, + profileModel); + + JSONObject tempJsonObject; + + final JSONArray childCommentsArray; + final int childCommentsLen; + if ((tempJsonObject = comment.optJSONObject("edge_threaded_comments")) != null && + (childCommentsArray = tempJsonObject.optJSONArray("edges")) != null + && (childCommentsLen = childCommentsArray.length()) > 0) { + + final String childEndCursor; + final boolean hasNextPage; + if ((tempJsonObject = tempJsonObject.optJSONObject("page_info")) != null) { + childEndCursor = tempJsonObject.optString("end_cursor"); + hasNextPage = tempJsonObject.optBoolean("has_next_page", !Utils.isEmpty(childEndCursor)); + } else { + childEndCursor = null; + hasNextPage = false; + } + + final CommentModel[] childCommentModels = new CommentModel[childCommentsLen]; + for (int j = 0; j < childCommentsLen; ++j) { + final JSONObject childComment = childCommentsArray.getJSONObject(j).getJSONObject("node"); + + tempJsonObject = childComment.getJSONObject("owner"); + final ProfileModel childProfileModel = new ProfileModel(false, false, + tempJsonObject.getString(Constants.EXTRAS_ID), + tempJsonObject.getString(Constants.EXTRAS_USERNAME), + null, null, null, + tempJsonObject.getString("profile_pic_url"), + null, 0, 0, 0); + + tempJsonObject = childComment.optJSONObject("edge_liked_by"); + childCommentModels[j] = new CommentModel(childComment.getString(Constants.EXTRAS_ID), + childComment.getString("text"), + childComment.getLong("created_at"), + tempJsonObject != null ? tempJsonObject.optLong("count", 0) : 0, + childProfileModel); + } + + childCommentModels[childCommentsLen - 1].setPageCursor(hasNextPage, childEndCursor); + + commentModels[i].setChildCommentModels(childCommentModels); + } + } + + Collections.addAll(commentModelsList, commentModels); + } + + conn.disconnect(); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.ASYNC_COMMENTS_FETCHER, "getParentComments", + new Pair<>("commentModelsList.size", commentModelsList.size())); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + break; + } + } + + return commentModelsList; + } +} diff --git a/app/src/main/java/awais/instagrabber/asyncs/DiscoverFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/DiscoverFetcher.java new file mode 100755 index 00000000..aa2a9950 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/DiscoverFetcher.java @@ -0,0 +1,194 @@ +package awais.instagrabber.asyncs; + +import android.os.AsyncTask; +import android.os.Environment; +import android.util.Log; +import android.util.Pair; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.File; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.DiscoverItemModel; +import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; +import awaisomereport.LogCollector; + +import static awais.instagrabber.utils.Constants.FOLDER_PATH; +import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO; +import static awais.instagrabber.utils.Utils.logCollector; +import static awais.instagrabber.utils.Utils.settingsHelper; + +public final class DiscoverFetcher extends AsyncTask { + private final String maxId; + private final FetchListener fetchListener; + private int lastId = 0; + private boolean isFirst, moreAvailable; + private String nextMaxId; + + public DiscoverFetcher(final String maxId, final FetchListener fetchListener, final boolean isFirst) { + this.maxId = maxId == null ? "" : "&max_id=" + maxId; + this.fetchListener = fetchListener; + this.isFirst = isFirst; + } + + @Nullable + @Override + protected final DiscoverItemModel[] doInBackground(final Void... voids) { + // to check if file exists + final File downloadDir = new File(Environment.getExternalStorageDirectory(), "Download"); + File customDir = null; + if (settingsHelper.getBoolean(FOLDER_SAVE_TO)) { + final String customPath = settingsHelper.getString(FOLDER_PATH); + if (!Utils.isEmpty(customPath)) customDir = new File(customPath); + } + + DiscoverItemModel[] result = null; + + final ArrayList discoverItemModels = fetchItems(downloadDir, customDir, null, maxId); + if (discoverItemModels != null) { + result = discoverItemModels.toArray(new DiscoverItemModel[0]); + if (result.length > 0) { + final DiscoverItemModel lastModel = result[result.length - 1]; + if (lastModel != null) lastModel.setMore(moreAvailable, nextMaxId); + } + } + + return result; + } + + private ArrayList fetchItems(final File downloadDir, final File customDir, + ArrayList discoverItemModels, final String maxId) { + try { + final String url = "https://www.instagram.com/explore/grid/?is_prefetch=false&omit_cover_media=true&module=explore_popular" + + "&use_sectional_payload=false&cluster_id=explore_all%3A0&include_fixed_destinations=true" + maxId; + + final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection(); + + urlConnection.setUseCaches(false); + urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Linux; Android 8.1.0; motorola one Build/OPKS28.63-18-3; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36 Instagram 72.0.0.21.98 Android (27/8.1.0; 320dpi; 720x1362; motorola; motorola one; deen_sprout; qcom; pt_BR; 132081645)"); + + if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { + final JSONObject discoverResponse = new JSONObject(Utils.readFromConnection(urlConnection)); + + moreAvailable = discoverResponse.getBoolean("more_available"); + nextMaxId = discoverResponse.getString("next_max_id"); + + final JSONArray sectionalItems = discoverResponse.getJSONArray("sectional_items"); + if (discoverItemModels == null) discoverItemModels = new ArrayList<>(sectionalItems.length() * 2); + + for (int i = 0; i < sectionalItems.length(); ++i) { + final JSONObject sectionItem = sectionalItems.getJSONObject(i); + + final String feedType = sectionItem.getString("feed_type"); + final String layoutType = sectionItem.getString("layout_type"); + + if (sectionItem.has("layout_content") && feedType.equals("media")) { + final JSONObject layoutContent = sectionItem.getJSONObject("layout_content"); + + if ("media_grid".equals(layoutType)) { + final JSONArray medias = layoutContent.getJSONArray("medias"); + for (int j = 0; j < medias.length(); ++j) + discoverItemModels.add(makeDiscoverModel(downloadDir, customDir, + medias.getJSONObject(j).getJSONObject("media"))); + + } else { + final boolean isOneSide = "one_by_two_left".equals(layoutType); + if (isOneSide || "two_by_two_right".equals(layoutType)) { + + final JSONObject layoutItem = layoutContent.getJSONObject(isOneSide ? "one_by_two_item" : "two_by_two_item"); + if (layoutItem.has("media")) + discoverItemModels.add(makeDiscoverModel(downloadDir, customDir, + layoutItem.getJSONObject("media"))); + + if (layoutContent.has("fill_items")) { + final JSONArray fillItems = layoutContent.getJSONArray("fill_items"); + for (int j = 0; j < fillItems.length(); ++j) + discoverItemModels.add(makeDiscoverModel(downloadDir, customDir, + fillItems.getJSONObject(j).getJSONObject("media"))); + } + } + } + } + } + + discoverItemModels.trimToSize(); + urlConnection.disconnect(); + + // hack to fetch 50+ items + if (this.isFirst) { + final int size = discoverItemModels.size(); + if (size > 50) this.isFirst = false; + discoverItemModels = fetchItems(downloadDir, customDir, discoverItemModels, + "&max_id=" + (lastId++)); + } + } else { + urlConnection.disconnect(); + } + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.ASYNC_DISCOVER_FETCHER, "fetchItems", + new Pair<>("maxId", maxId), + new Pair<>("lastId", lastId), + new Pair<>("isFirst", isFirst), + new Pair<>("nextMaxId", nextMaxId)); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return discoverItemModels; + } + + @NonNull + private DiscoverItemModel makeDiscoverModel(final File downloadDir, final File customDir, + @NonNull final JSONObject media) throws Exception { + final JSONObject user = media.getJSONObject(Constants.EXTRAS_USER); + final String username = user.getString(Constants.EXTRAS_USERNAME); + // final ProfileModel userProfileModel = new ProfileModel(user.getBoolean("is_private"), + // user.getBoolean("is_verified"), + // String.valueOf(user.get("pk")), + // username, + // user.getString("full_name"), + // null, + // user.getString("profile_pic_url"), null, + // 0, 0, 0); + + // final String comment; + // if (!media.has("caption")) comment = null; + // else { + // final Object caption = media.get("caption"); + // comment = caption instanceof JSONObject ? ((JSONObject) caption).getString("text") : null; + // } + + final MediaItemType mediaType = Utils.getMediaItemType(media.getInt("media_type")); + + final DiscoverItemModel model = new DiscoverItemModel(mediaType, + media.getString(Constants.EXTRAS_ID), + media.getString("code"), + Utils.getThumbnailUrl(media, mediaType)); + + Utils.checkExistence(downloadDir, customDir, username, + mediaType == MediaItemType.MEDIA_TYPE_SLIDER, -1, model); + + return model; + } + + @Override + protected void onPreExecute() { + if (fetchListener != null) fetchListener.doBefore(); + } + + @Override + protected void onPostExecute(final DiscoverItemModel[] discoverItemModels) { + if (fetchListener != null) fetchListener.onResult(discoverItemModels); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/asyncs/DownloadAsync.java b/app/src/main/java/awais/instagrabber/asyncs/DownloadAsync.java new file mode 100755 index 00000000..57c2d813 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/DownloadAsync.java @@ -0,0 +1,248 @@ +package awais.instagrabber.asyncs; + +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.media.MediaMetadataRetriever; +import android.media.MediaScannerConnection; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Environment; +import android.util.Log; +import android.util.Pair; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; +import androidx.core.app.NotificationCompat; +import androidx.core.app.NotificationManagerCompat; +import androidx.core.content.FileProvider; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.net.URL; +import java.net.URLConnection; +import java.util.concurrent.atomic.AtomicReference; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.R; +import awais.instagrabber.activities.ProfileViewer; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.utils.Utils; + +import static awais.instagrabber.utils.Utils.CHANNEL_ID; +import static awais.instagrabber.utils.Utils.CHANNEL_NAME; +import static awais.instagrabber.utils.Utils.NOTIF_GROUP_NAME; +import static awais.instagrabber.utils.Utils.isChannelCreated; +import static awais.instagrabber.utils.Utils.logCollector; +import static awais.instagrabber.utils.Utils.notificationManager; +import static awaisomereport.LogCollector.LogFile; + +public final class DownloadAsync extends AsyncTask { + private static int lastNotifId = 1; + private final int currentNotifId; + private final AtomicReference context; + private final File outFile; + private final String url; + private final FetchListener fetchListener; + private final Resources resources; + private final NotificationCompat.Builder downloadNotif; + private String shortCode, username; + + public DownloadAsync(final Context context, final String url, final File outFile, final FetchListener fetchListener) { + this.context = new AtomicReference<>(context); + this.resources = context.getResources(); + this.url = url; + this.outFile = outFile; + this.fetchListener = fetchListener; + this.shortCode = this.username = resources.getString(R.string.downloader_started); + this.currentNotifId = ++lastNotifId; + if (++lastNotifId + 1 == Integer.MAX_VALUE) lastNotifId = 1; + + if (notificationManager == null) + notificationManager = NotificationManagerCompat.from(context.getApplicationContext()); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !isChannelCreated) { + notificationManager.createNotificationChannel(new NotificationChannel(CHANNEL_ID, + CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH)); + isChannelCreated = true; + } + + @StringRes final int titleRes = context instanceof ProfileViewer ? R.string.downloader_downloading_pfp : R.string.downloader_downloading_post; + + downloadNotif = new NotificationCompat.Builder(context, CHANNEL_ID).setCategory(NotificationCompat.CATEGORY_STATUS) + .setSmallIcon(R.mipmap.ic_launcher).setContentText(shortCode == null ? username : shortCode).setOngoing(true) + .setProgress(100, 0, false).setAutoCancel(false).setOnlyAlertOnce(true) + .setContentTitle(resources.getString(titleRes)); + + notificationManager.notify(currentNotifId, downloadNotif.build()); + } + + public DownloadAsync setItems(final String shortCode, final String username) { + this.shortCode = shortCode; + this.username = username; + if (downloadNotif != null) downloadNotif.setContentText(this.shortCode == null ? this.username : this.shortCode); + return this; + } + + @Nullable + @Override + protected File doInBackground(final Void... voids) { + try { + final URLConnection urlConnection = new URL(url).openConnection(); + final long fileSize = Build.VERSION.SDK_INT >= 24 ? urlConnection.getContentLengthLong() : + urlConnection.getContentLength(); + float totalRead = 0; + + try (final BufferedInputStream bis = new BufferedInputStream(urlConnection.getInputStream()); + final FileOutputStream fos = new FileOutputStream(outFile)) { + final byte[] buffer = new byte[0x2000]; + + int count; + boolean deletedIPTC = false; + while ((count = bis.read(buffer, 0, 0x2000)) != -1) { + totalRead = totalRead + count; + + if (!deletedIPTC) { + int iptcStart = -1; + int fbmdStart = -1; + int fbmdBytesLen = -1; + + for (int i = 0; i < buffer.length; ++i) { + if (buffer[i] == (byte) 0xFF && buffer[i + 1] == (byte) 0xED) + iptcStart = i; + else if (buffer[i] == (byte) 'F' && buffer[i + 1] == (byte) 'B' + && buffer[i + 2] == (byte) 'M' && buffer[i + 3] == (byte) 'D') { + fbmdStart = i; + fbmdBytesLen = buffer[i - 10] << 24 | (buffer[i - 9] & 0xFF) << 16 | + (buffer[i - 8] & 0xFF) << 8 | (buffer[i - 7] & 0xFF) | + (buffer[i - 6] & 0xFF); + break; + } + } + + if (iptcStart != -1 && fbmdStart != -1 && fbmdBytesLen != -1) { + final int fbmdDataLen = (iptcStart + (fbmdStart - iptcStart) + (fbmdBytesLen - iptcStart)) - 4; + + fos.write(buffer, 0, iptcStart); + fos.write(buffer, fbmdDataLen + iptcStart, count - fbmdDataLen - iptcStart); + + publishProgress(totalRead * 100f / fileSize); + + deletedIPTC = true; + continue; + } + } + + fos.write(buffer, 0, count); + publishProgress(totalRead * 100f / fileSize); + } + fos.flush(); + } + + return outFile; + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogFile.ASYNC_DOWNLOADER, "doInBackground", + new Pair<>("context", context.get()), + new Pair<>("resources", resources), + new Pair<>("lastNotifId", lastNotifId), + new Pair<>("downloadNotif", downloadNotif), + new Pair<>("currentNotifId", currentNotifId), + new Pair<>("notificationManager", notificationManager)); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + return null; + } + + @Override + protected void onPreExecute() { + if (fetchListener != null) fetchListener.doBefore(); + } + + @Override + protected void onProgressUpdate(@NonNull final Float... values) { + if (downloadNotif != null) { + downloadNotif.setProgress(100, values[0].intValue(), false); + notificationManager.notify(currentNotifId, downloadNotif.build()); + } + } + + @Override + protected void onPostExecute(final File result) { + if (result != null) { + final Context context = this.context.get(); + + context.sendBroadcast(Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT ? + new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.fromFile(Environment.getExternalStorageDirectory())) : + new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(result.getAbsoluteFile())) + ); + MediaScannerConnection.scanFile(context, new String[]{result.getAbsolutePath()}, null, null); + + if (notificationManager != null) { + final Uri uri = FileProvider.getUriForFile(context, "awais.instagrabber.provider", result); + + final ContentResolver contentResolver = context.getContentResolver(); + Bitmap bitmap = null; + if (Utils.isImage(uri, contentResolver)) { + try { + bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(uri)); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogFile.ASYNC_DOWNLOADER, "onPostExecute::bitmap_1"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } + + if (bitmap == null) { + final MediaMetadataRetriever retriever = new MediaMetadataRetriever(); + try { + try { + retriever.setDataSource(context, uri); + } catch (final Exception e) { + retriever.setDataSource(result.getAbsolutePath()); + } + bitmap = retriever.getFrameAtTime(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) + try { + retriever.close(); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogFile.ASYNC_DOWNLOADER, "onPostExecute::bitmap_2"); + } + } catch (final Exception e) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + if (logCollector != null) + logCollector.appendException(e, LogFile.ASYNC_DOWNLOADER, "onPostExecute::bitmap_3"); + } + } + + final String downloadComplete = resources.getString(R.string.downloader_complete); + + downloadNotif.setContentText(null).setContentTitle(downloadComplete).setProgress(0, 0, false) + .setWhen(System.currentTimeMillis()).setOngoing(false).setOnlyAlertOnce(false).setAutoCancel(true) + .setGroup(NOTIF_GROUP_NAME).setGroupSummary(true).setContentIntent( + PendingIntent.getActivity(context, 2020, new Intent(Intent.ACTION_VIEW, uri) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_FROM_BACKGROUND | Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION) + .putExtra(Intent.EXTRA_STREAM, uri), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT)); + + if (bitmap != null) + downloadNotif.setStyle(new NotificationCompat.BigPictureStyle().setBigContentTitle(downloadComplete).bigPicture(bitmap)) + .setLargeIcon(bitmap).setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL); + + notificationManager.cancel(currentNotifId); + notificationManager.notify(currentNotifId + 1, downloadNotif.build()); + } + } + + if (fetchListener != null) fetchListener.onResult(result); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/asyncs/FeedFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/FeedFetcher.java new file mode 100755 index 00000000..40d3a9de --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/FeedFetcher.java @@ -0,0 +1,194 @@ +package awais.instagrabber.asyncs; + +import android.os.AsyncTask; +import android.util.Log; + +import androidx.annotation.Nullable; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.models.FeedModel; +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.models.ViewerPostModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; +import awaisomereport.LogCollector; + +import static awais.instagrabber.utils.Utils.logCollector; + +public final class FeedFetcher extends AsyncTask { + private static final int maxItemsToLoad = 25; // max is 50, but that's too many posts, setting more than 30 is gay + private final String endCursor; + private final FetchListener fetchListener; + + public FeedFetcher(final FetchListener fetchListener) { + this.endCursor = ""; + this.fetchListener = fetchListener; + } + + public FeedFetcher(final String endCursor, final FetchListener fetchListener) { + this.endCursor = endCursor == null ? "" : endCursor; + this.fetchListener = fetchListener; + } + + @Nullable + @Override + protected final FeedModel[] doInBackground(final Void... voids) { + FeedModel[] result = null; + try { + // + // stories: 04334405dbdef91f2c4e207b84c204d7 && https://i.instagram.com/api/v1/feed/reels_tray/ + // https://www.instagram.com/graphql/query/?query_hash=04334405dbdef91f2c4e207b84c204d7&variables={"only_stories":true,"stories_prefetch":false,"stories_video_dash_manifest":false} + // /////////////////////////////////////////////// + // feed: + // https://www.instagram.com/graphql/query/?query_hash=6b838488258d7a4820e48d209ef79eb1&variables= + // {"cached_feed_item_ids":[],"fetch_media_item_count":12,"fetch_media_item_cursor":"","fetch_comment_count":4,"fetch_like":3,"has_stories":false,"has_threaded_comments":true} + // only used: fetch_media_item_cursor, fetch_media_item_count: 100 (max 50), has_threaded_comments = true + // ////////////////////////////////////////////// + // more unknowns: https://github.com/qsniyg/rssit/blob/master/rssit/generators/instagram.py + // + + final String url = "https://www.instagram.com/graphql/query/?query_hash=6b838488258d7a4820e48d209ef79eb1&variables=" + + "{\"fetch_media_item_count\":" + maxItemsToLoad + ",\"has_threaded_comments\":true,\"fetch_media_item_cursor\":\"" + endCursor + "\"}"; + final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection(); + + if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { + final JSONObject timelineFeed = new JSONObject(Utils.readFromConnection(urlConnection)).getJSONObject("data") + .getJSONObject(Constants.EXTRAS_USER).getJSONObject("edge_web_feed_timeline"); + + final String endCursor; + final boolean hasNextPage; + + final JSONObject pageInfo = timelineFeed.getJSONObject("page_info"); + if (pageInfo.has("has_next_page")) { + hasNextPage = pageInfo.getBoolean("has_next_page"); + endCursor = hasNextPage ? pageInfo.getString("end_cursor") : null; + } else { + hasNextPage = false; + endCursor = null; + } + + final JSONArray feedItems = timelineFeed.getJSONArray("edges"); + + final int feedLen = feedItems.length(); + final ArrayList feedModelsList = new ArrayList<>(feedLen); + for (int i = 0; i < feedLen; ++i) { + final JSONObject feedItem = feedItems.getJSONObject(i).getJSONObject("node"); + final String mediaType = feedItem.optString("__typename"); + if (mediaType.isEmpty() || "GraphSuggestedUserFeedUnit".equals(mediaType)) continue; + + final boolean isVideo = feedItem.optBoolean("is_video"); + final long videoViews = feedItem.optLong("video_view_count", 0); + + final String displayUrl = feedItem.getString("display_url"); + final String resourceUrl; + + if (isVideo) resourceUrl = feedItem.getString("video_url"); + else resourceUrl = feedItem.has("display_resources") ? Utils.getHighQualityImage(feedItem) : displayUrl; + + ProfileModel profileModel = null; + if (feedItem.has("owner")) { + final JSONObject owner = feedItem.getJSONObject("owner"); + profileModel = new ProfileModel(owner.optBoolean("is_private"), + owner.optBoolean("is_verified"), + owner.getString(Constants.EXTRAS_ID), + owner.getString(Constants.EXTRAS_USERNAME), + owner.optString("full_name"), + null, null, + owner.getString("profile_pic_url"), + null, 0, 0, 0); + } + + JSONObject tempJsonObject = feedItem.optJSONObject("edge_media_preview_comment"); + final long commentsCount = tempJsonObject != null ? tempJsonObject.optLong("count") : 0; + + tempJsonObject = feedItem.optJSONObject("edge_media_to_caption"); + final JSONArray captions = tempJsonObject != null ? tempJsonObject.getJSONArray("edges") : null; + + String captionText = null; + if (captions != null && captions.length() > 0) { + if ((tempJsonObject = captions.optJSONObject(0)) != null && + (tempJsonObject = tempJsonObject.optJSONObject("node")) != null) + captionText = tempJsonObject.getString("text"); + } + + final FeedModel feedModel = new FeedModel(profileModel, + isVideo ? MediaItemType.MEDIA_TYPE_VIDEO : MediaItemType.MEDIA_TYPE_IMAGE, + videoViews, + feedItem.getString(Constants.EXTRAS_ID), + resourceUrl, + displayUrl, + feedItem.getString(Constants.EXTRAS_SHORTCODE), + captionText, + commentsCount, + feedItem.optLong("taken_at_timestamp", -1)); + + final boolean isSlider = "GraphSidecar".equals(mediaType) && feedItem.has("edge_sidecar_to_children"); + + if (isSlider) { + final JSONObject sidecar = feedItem.optJSONObject("edge_sidecar_to_children"); + if (sidecar != null) { + final JSONArray children = sidecar.optJSONArray("edges"); + + if (children != null) { + final ViewerPostModel[] sliderItems = new ViewerPostModel[children.length()]; + + for (int j = 0; j < sliderItems.length; ++j) { + final JSONObject node = children.optJSONObject(j).getJSONObject("node"); + final boolean isChildVideo = node.optBoolean("is_video"); + + sliderItems[j] = new ViewerPostModel( + isChildVideo ? MediaItemType.MEDIA_TYPE_VIDEO : MediaItemType.MEDIA_TYPE_IMAGE, + node.getString(Constants.EXTRAS_ID), + isChildVideo ? node.getString("video_url") : Utils.getHighQualityImage(node), + null, null, null, + node.optLong("video_view_count", -1), -1); + + sliderItems[j].setSliderDisplayUrl(node.getString("display_url")); + } + + feedModel.setSliderItems(sliderItems); + } + } + } + + feedModelsList.add(feedModel); + } + + feedModelsList.trimToSize(); + + final FeedModel[] feedModels = feedModelsList.toArray(new FeedModel[0]); + if (feedModels[feedModels.length - 1] != null) + feedModels[feedModels.length - 1].setPageCursor(hasNextPage, endCursor); + + result = feedModels; + } + + urlConnection.disconnect(); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.ASYNC_FEED_FETCHER, "doInBackground"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return result; + } + + @Override + protected void onPreExecute() { + if (fetchListener != null) fetchListener.doBefore(); + } + + @Override + protected void onPostExecute(final FeedModel[] postModels) { + if (fetchListener != null) fetchListener.onResult(postModels); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/asyncs/FeedStoriesFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/FeedStoriesFetcher.java new file mode 100755 index 00000000..8084eab9 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/FeedStoriesFetcher.java @@ -0,0 +1,103 @@ +package awais.instagrabber.asyncs; + +import android.os.AsyncTask; +import android.util.Log; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.net.HttpURLConnection; +import java.net.URL; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.FeedStoryModel; +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; +import awaisomereport.LogCollector.LogFile; + +import static awais.instagrabber.utils.Utils.logCollector; + +public final class FeedStoriesFetcher extends AsyncTask { + private final FetchListener fetchListener; + + public FeedStoriesFetcher(final FetchListener fetchListener) { + this.fetchListener = fetchListener; + } + + @Override + protected FeedStoryModel[] doInBackground(final Void... voids) { + FeedStoryModel[] result = null; + String url = "https://www.instagram.com/graphql/query/?query_hash=b7b84d884400bc5aa7cfe12ae843a091&variables=" + + "{\"only_stories\":true,\"stories_prefetch\":false,\"stories_video_dash_manifest\":false}"; + + try { + HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setInstanceFollowRedirects(false); + conn.setUseCaches(false); + conn.connect(); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + final JSONArray feedStoriesReel = new JSONObject(Utils.readFromConnection(conn)) + .getJSONObject("data") + .getJSONObject(Constants.EXTRAS_USER) + .getJSONObject("feed_reels_tray") + .getJSONObject("edge_reels_tray_to_reel") + .getJSONArray("edges"); + + conn.disconnect(); + + final int storiesLen = feedStoriesReel.length(); + final FeedStoryModel[] feedStoryModels = new FeedStoryModel[storiesLen]; + final String[] feedStoryIDs = new String[storiesLen]; + + for (int i = 0; i < storiesLen; ++i) { + final JSONObject node = feedStoriesReel.getJSONObject(i).getJSONObject("node"); + + final JSONObject user = node.getJSONObject(node.has("user") ? "user" : "owner"); + final ProfileModel profileModel = new ProfileModel(false, false, + user.getString("id"), + user.getString("username"), + null, null, null, + user.getString("profile_pic_url"), + null, 0, 0, 0); + + final String id = node.getString("id"); + feedStoryIDs[i] = id; + feedStoryModels[i] = new FeedStoryModel(id, profileModel); + } + + url = "https://www.instagram.com/graphql/query/?query_hash=0a85e6ea60a4c99edc58ab2f3d17cfdf&variables=" + + "{\"reel_ids\":" + Utils.highlightIdsMerger(feedStoryIDs) + ",\"precomposed_overlay\":false}"; + conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setInstanceFollowRedirects(false); + conn.setUseCaches(false); + conn.connect(); + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + Utils.putHighlightModels(conn, feedStoryModels); + } + + result = feedStoryModels; + } + + conn.disconnect(); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogFile.ASYNC_FEED_STORY_FETCHER, "doInBackground"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return result; + } + + @Override + protected void onPreExecute() { + if (fetchListener != null) fetchListener.doBefore(); + } + + @Override + protected void onPostExecute(final FeedStoryModel[] result) { + if (fetchListener != null) fetchListener.onResult(result); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/asyncs/FollowFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/FollowFetcher.java new file mode 100755 index 00000000..103657d1 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/FollowFetcher.java @@ -0,0 +1,101 @@ +package awais.instagrabber.asyncs; + +import android.os.AsyncTask; +import android.util.Log; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.net.HttpURLConnection; +import java.net.URL; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.FollowModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; +import awaisomereport.LogCollector; + +import static awais.instagrabber.utils.Utils.logCollector; + +public final class FollowFetcher extends AsyncTask { + private final String endCursor, id; + private final boolean isFollowers; + private final FetchListener fetchListener; + + public FollowFetcher(final String id, final boolean isFollowers, final FetchListener fetchListener) { + this.id = id; + this.endCursor = ""; + this.isFollowers = isFollowers; + this.fetchListener = fetchListener; + } + + public FollowFetcher(final String id, final boolean isFollowers, final String endCursor, final FetchListener fetchListener) { + this.id = id; + this.endCursor = endCursor == null ? "" : endCursor; + this.isFollowers = isFollowers; + this.fetchListener = fetchListener; + } + + @Override + protected void onPreExecute() { + if (fetchListener != null) fetchListener.doBefore(); + } + + @Override + protected FollowModel[] doInBackground(final Void... voids) { + FollowModel[] result = null; + final String url = "https://www.instagram.com/graphql/query/?query_id=" + (isFollowers ? "17851374694183129" : "17874545323001329") + + "&id=" + id + "&first=50&after=" + endCursor; + + try { + final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setInstanceFollowRedirects(false); + conn.setUseCaches(false); + conn.connect(); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + final JSONObject data = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("data") + .getJSONObject(Constants.EXTRAS_USER).getJSONObject(isFollowers ? "edge_followed_by" : "edge_follow"); + + final String endCursor; + final boolean hasNextPage; + + final JSONObject pageInfo = data.getJSONObject("page_info"); + if (pageInfo.has("has_next_page")) { + hasNextPage = pageInfo.getBoolean("has_next_page"); + endCursor = hasNextPage ? pageInfo.getString("end_cursor") : null; + } else { + hasNextPage = false; + endCursor = null; + } + + final JSONArray edges = data.getJSONArray("edges"); + final FollowModel[] models = new FollowModel[edges.length()]; + for (int i = 0; i < models.length; ++i) { + final JSONObject followNode = edges.getJSONObject(i).getJSONObject("node"); + models[i] = new FollowModel(followNode.getString(Constants.EXTRAS_ID), followNode.getString(Constants.EXTRAS_USERNAME), + followNode.getString("full_name"), followNode.getString("profile_pic_url")); + } + + if (models[models.length - 1] != null) + models[models.length - 1].setPageCursor(hasNextPage, endCursor); + + result = models; + } + + conn.disconnect(); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.ASYNC_FOLLOW_FETCHER, "doInBackground"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return result; + } + + @Override + protected void onPostExecute(final FollowModel[] result) { + if (fetchListener != null) fetchListener.onResult(result); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/asyncs/HighlightsFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/HighlightsFetcher.java new file mode 100755 index 00000000..b2e756e8 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/HighlightsFetcher.java @@ -0,0 +1,87 @@ +package awais.instagrabber.asyncs; + +import android.os.AsyncTask; +import android.util.Log; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.net.HttpURLConnection; +import java.net.URL; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.HighlightModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; + +public final class HighlightsFetcher extends AsyncTask { + private final String id; + private final FetchListener fetchListener; + + public HighlightsFetcher(final String id, final FetchListener fetchListener) { + this.id = id; + this.fetchListener = fetchListener; + } + + @Override + protected HighlightModel[] doInBackground(final Void... voids) { + HighlightModel[] result = null; + String url = "https://www.instagram.com/graphql/query/?query_hash=7c16654f22c819fb63d1183034a5162f&variables=" + + "{\"user_id\":\"" + id + "\",\"include_chaining\":false,\"include_reel\":true,\"include_suggested_users\":false," + + "\"include_logged_out_extras\":false,\"include_highlight_reels\":true}"; + + try { + HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setInstanceFollowRedirects(false); + conn.setUseCaches(false); + conn.connect(); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + final JSONArray highlightsReel = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("data") + .getJSONObject(Constants.EXTRAS_USER).getJSONObject("edge_highlight_reels").getJSONArray("edges"); + + final int length = highlightsReel.length(); + final HighlightModel[] highlightModels = new HighlightModel[length]; + final String[] highlightIds = new String[length]; + for (int i = 0; i < length; ++i) { + final JSONObject highlightNode = highlightsReel.getJSONObject(i).getJSONObject("node"); + final String id = highlightNode.getString(Constants.EXTRAS_ID); + highlightIds[i] = id; + highlightModels[i] = new HighlightModel( + highlightNode.getString("title"), + highlightNode.getJSONObject("cover_media").getString("thumbnail_src") + ); + } + + conn.disconnect(); + + // a22a50ce4582220909e302d6eb84d259 + // 45246d3fe16ccc6577e0bd297a5db1ab + url = "https://www.instagram.com/graphql/query/?query_hash=a22a50ce4582220909e302d6eb84d259&variables=" + + "{\"highlight_reel_ids\":" + Utils.highlightIdsMerger(highlightIds) + ",\"reel_ids\":[],\"location_ids\":[],\"precomposed_overlay\":false}"; + conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setInstanceFollowRedirects(false); + conn.setUseCaches(false); + conn.connect(); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + Utils.putHighlightModels(conn, highlightModels); + } + + result = highlightModels; + } + + conn.disconnect(); + } catch (Exception e) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return result; + } + + @Override + protected void onPostExecute(final HighlightModel[] result) { + if (fetchListener != null) fetchListener.onResult(result); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java new file mode 100755 index 00000000..9fe076f4 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java @@ -0,0 +1,146 @@ +package awais.instagrabber.asyncs; + +import android.os.AsyncTask; +import android.os.Environment; +import android.util.Log; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.File; +import java.net.HttpURLConnection; +import java.net.URL; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.models.ViewerPostModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; +import awaisomereport.LogCollector; + +import static awais.instagrabber.utils.Constants.FOLDER_PATH; +import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO; +import static awais.instagrabber.utils.Utils.logCollector; + +public final class PostFetcher extends AsyncTask { + private final String shortCode; + private final FetchListener fetchListener; + + public PostFetcher(final String shortCode, final FetchListener fetchListener) { + this.shortCode = shortCode; + this.fetchListener = fetchListener; + } + + @Override + protected ViewerPostModel[] doInBackground(final Void... voids) { + ViewerPostModel[] result = null; + try { + final HttpURLConnection conn = (HttpURLConnection) new URL("https://www.instagram.com/p/" + shortCode + "/?__a=1").openConnection(); + conn.setUseCaches(false); + conn.connect(); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + // to check if file exists + final File downloadDir = new File(Environment.getExternalStorageDirectory(), "Download"); + File customDir = null; + if (Utils.settingsHelper.getBoolean(FOLDER_SAVE_TO)) { + final String customPath = Utils.settingsHelper.getString(FOLDER_PATH); + if (!Utils.isEmpty(customPath)) customDir = new File(customPath); + } + + final JSONObject media = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("graphql") + .getJSONObject("shortcode_media"); + + final String username = media.has("owner") ? media.getJSONObject("owner").getString(Constants.EXTRAS_USERNAME) : null; + + final long timestamp = media.getLong("taken_at_timestamp"); + + final boolean isVideo = media.has("is_video") && media.optBoolean("is_video"); + final boolean isSlider = media.has("edge_sidecar_to_children"); + + final MediaItemType mediaItemType; + if (isSlider) mediaItemType = MediaItemType.MEDIA_TYPE_SLIDER; + else if (isVideo) mediaItemType = MediaItemType.MEDIA_TYPE_VIDEO; + else mediaItemType = MediaItemType.MEDIA_TYPE_IMAGE; + + final String postCaption; + final JSONObject mediaToCaption = media.optJSONObject("edge_media_to_caption"); + if (mediaToCaption == null) postCaption = null; + else { + final JSONArray captions = mediaToCaption.optJSONArray("edges"); + postCaption = captions != null && captions.length() > 0 ? + captions.getJSONObject(0).getJSONObject("node").optString("text") : null; + } + + JSONObject commentObject = media.optJSONObject("edge_media_to_parent_comment"); + final long commentsCount = commentObject != null ? commentObject.optLong("count") : 0; + + String endCursor = null; + if (commentObject != null && (commentObject = commentObject.optJSONObject("page_info")) != null) + endCursor = commentObject.optString("end_cursor"); + + if (mediaItemType != MediaItemType.MEDIA_TYPE_SLIDER) { + final ViewerPostModel postModel = new ViewerPostModel(mediaItemType, + media.getString(Constants.EXTRAS_ID), + isVideo ? media.getString("video_url") : Utils.getHighQualityImage(media), + shortCode, + Utils.isEmpty(postCaption) ? null : postCaption, + username, + isVideo && media.has("video_view_count") ? media.getLong("video_view_count") : -1, + timestamp); + + postModel.setCommentsCount(commentsCount); + postModel.setCommentsEndCursor(endCursor); + + Utils.checkExistence(downloadDir, customDir, username, false, -1, postModel); + + result = new ViewerPostModel[]{postModel}; + + } else { + final JSONArray children = media.getJSONObject("edge_sidecar_to_children").getJSONArray("edges"); + final ViewerPostModel[] postModels = new ViewerPostModel[children.length()]; + + for (int i = 0; i < postModels.length; ++i) { + final JSONObject node = children.getJSONObject(i).getJSONObject("node"); + final boolean isChildVideo = node.getBoolean("is_video"); + + postModels[i] = new ViewerPostModel(isChildVideo ? MediaItemType.MEDIA_TYPE_VIDEO : MediaItemType.MEDIA_TYPE_IMAGE, + node.getString(Constants.EXTRAS_ID), + isChildVideo ? node.getString("video_url") : Utils.getHighQualityImage(node), + node.getString(Constants.EXTRAS_SHORTCODE), + postCaption, + username, + isChildVideo && node.has("video_view_count") ? node.getLong("video_view_count") : -1, + timestamp); + postModels[i].setSliderDisplayUrl(node.getString("display_url")); + + Utils.checkExistence(downloadDir, customDir, username, true, i, postModels[i]); + } + + postModels[0].setCommentsCount(commentsCount); + postModels[0].setCommentsEndCursor(endCursor); + + result = postModels; + } + } + + conn.disconnect(); + } catch (Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.ASYNC_POST_FETCHER, "doInBackground"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + return result; + } + + @Override + protected void onPreExecute() { + if (fetchListener != null) fetchListener.doBefore(); + } + + @Override + protected void onPostExecute(final ViewerPostModel[] postModels) { + if (fetchListener != null) fetchListener.onResult(postModels); + } +} diff --git a/app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java new file mode 100755 index 00000000..42b2ce83 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/PostsFetcher.java @@ -0,0 +1,134 @@ +package awais.instagrabber.asyncs; + +import android.os.AsyncTask; +import android.os.Environment; +import android.util.Log; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.File; +import java.net.HttpURLConnection; +import java.net.URL; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.models.PostModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; +import awaisomereport.LogCollector; + +import static awais.instagrabber.utils.Constants.FOLDER_PATH; +import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO; +import static awais.instagrabber.utils.Utils.logCollector; + +public final class PostsFetcher extends AsyncTask { + private final String endCursor; + private final String id; + private final FetchListener fetchListener; + private String username; + + public PostsFetcher(final String id, final FetchListener fetchListener) { + this.id = id; + this.endCursor = ""; + this.fetchListener = fetchListener; + } + + public PostsFetcher(final String id, final String endCursor, final FetchListener fetchListener) { + this.id = id; + this.endCursor = endCursor == null ? "" : endCursor; + this.fetchListener = fetchListener; + } + + public PostsFetcher setUsername(final String username) { + this.username = username; + return this; + } + + @Override + protected PostModel[] doInBackground(final Void... voids) { + final boolean isHashTag = id.charAt(0) == '#'; + + final String url; + if (isHashTag) + url = "https://www.instagram.com/graphql/query/?query_hash=ded47faa9a1aaded10161a2ff32abb6b&variables=" + + "{\"tag_name\":\"" + id.substring(1) + "\",\"first\":150,\"after\":\"" + endCursor + "\"}"; + else + url = "https://www.instagram.com/graphql/query/?query_id=17880160963012870&id=" + id + "&first=50&after=" + endCursor; + + PostModel[] result = null; + try { + final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setUseCaches(false); + conn.connect(); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + // to check if file exists + final File downloadDir = new File(Environment.getExternalStorageDirectory(), "Download"); + File customDir = null; + if (Utils.settingsHelper.getBoolean(FOLDER_SAVE_TO)) { + final String customPath = Utils.settingsHelper.getString(FOLDER_PATH); + if (!Utils.isEmpty(customPath)) customDir = new File(customPath); + } + + final JSONObject mediaPosts = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("data") + .getJSONObject(isHashTag ? "hashtag" : Constants.EXTRAS_USER) + .getJSONObject(isHashTag ? "edge_hashtag_to_media" : "edge_owner_to_timeline_media"); + + final String endCursor; + final boolean hasNextPage; + + final JSONObject pageInfo = mediaPosts.getJSONObject("page_info"); + if (pageInfo.has("has_next_page")) { + hasNextPage = pageInfo.getBoolean("has_next_page"); + endCursor = hasNextPage ? pageInfo.getString("end_cursor") : null; + } else { + hasNextPage = false; + endCursor = null; + } + + final JSONArray edges = mediaPosts.getJSONArray("edges"); + final PostModel[] models = new PostModel[edges.length()]; + for (int i = 0; i < models.length; ++i) { + final JSONObject mediaNode = edges.getJSONObject(i).getJSONObject("node"); + final JSONArray captions = mediaNode.getJSONObject("edge_media_to_caption").getJSONArray("edges"); + + final boolean isSlider = mediaNode.has("__typename") && mediaNode.getString("__typename").equals("GraphSidecar"); + final boolean isVideo = mediaNode.getBoolean("is_video"); + + final MediaItemType itemType; + if (isSlider) itemType = MediaItemType.MEDIA_TYPE_SLIDER; + else if (isVideo) itemType = MediaItemType.MEDIA_TYPE_VIDEO; + else itemType = MediaItemType.MEDIA_TYPE_IMAGE; + + models[i] = new PostModel(itemType, mediaNode.getString(Constants.EXTRAS_ID), + mediaNode.getString("display_url"), mediaNode.getString("thumbnail_src"), + mediaNode.getString(Constants.EXTRAS_SHORTCODE), + captions.length() > 0 ? captions.getJSONObject(0).getJSONObject("node").getString("text") : null, + mediaNode.getLong("taken_at_timestamp")); + + Utils.checkExistence(downloadDir, customDir, username, isSlider, -1, models[i]); + } + + if (models[models.length - 1] != null) + models[models.length - 1].setPageCursor(hasNextPage, endCursor); + + result = models; + } + + conn.disconnect(); + } catch (Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.ASYNC_MAIN_POSTS_FETCHER, "doInBackground"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return result; + } + + @Override + protected void onPostExecute(final PostModel[] postModels) { + if (fetchListener != null) fetchListener.onResult(postModels); + } +} diff --git a/app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java new file mode 100755 index 00000000..c24735b8 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java @@ -0,0 +1,83 @@ +package awais.instagrabber.asyncs; + +import android.os.AsyncTask; +import android.util.Log; + +import androidx.annotation.Nullable; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.net.HttpURLConnection; +import java.net.URL; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; +import awaisomereport.LogCollector; + +import static awais.instagrabber.utils.Utils.logCollector; + +public final class ProfileFetcher extends AsyncTask { + private final FetchListener fetchListener; + private final String userName; + + public ProfileFetcher(String userName, FetchListener fetchListener) { + this.userName = userName; + this.fetchListener = fetchListener; + } + + @Nullable + @Override + protected ProfileModel doInBackground(final Void... voids) { + ProfileModel result = null; + + try { + final HttpURLConnection conn = (HttpURLConnection) new URL("https://www.instagram.com/" + userName + "/?__a=1").openConnection(); + conn.setUseCaches(true); + conn.connect(); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + final JSONObject user = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("graphql").getJSONObject(Constants.EXTRAS_USER); + + boolean isPrivate = user.getBoolean("is_private"); + final JSONObject timelineMedia = user.getJSONObject("edge_owner_to_timeline_media"); + if (timelineMedia.has("edges")) { + final JSONArray edges = timelineMedia.getJSONArray("edges"); + if (edges.length() > 0) isPrivate = false; + } + + String url = user.optString("external_url"); + if (Utils.isEmpty(url)) url = null; + + result = new ProfileModel(isPrivate, + user.getBoolean("is_verified"), + user.getString(Constants.EXTRAS_ID), + userName, + user.getString("full_name"), + user.getString("biography"), + url, + user.getString("profile_pic_url"), + user.getString("profile_pic_url_hd"), + timelineMedia.getLong("count"), + user.getJSONObject("edge_followed_by").getLong("count"), + user.getJSONObject("edge_follow").getLong("count")); + } + + conn.disconnect(); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.ASYNC_PROFILE_FETCHER, "doInBackground"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return result; + } + + @Override + protected void onPostExecute(final ProfileModel result) { + if (fetchListener != null) fetchListener.onResult(result); + } +} diff --git a/app/src/main/java/awais/instagrabber/asyncs/ProfilePictureFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/ProfilePictureFetcher.java new file mode 100755 index 00000000..a41583b1 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/ProfilePictureFetcher.java @@ -0,0 +1,120 @@ +package awais.instagrabber.asyncs; + +import android.os.AsyncTask; +import android.util.Log; +import android.util.Pair; + +import org.json.JSONObject; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.net.HttpURLConnection; +import java.net.URL; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.utils.Utils; +import awaisomereport.LogCollector; +import awais.instagrabber.models.enums.ProfilePictureFetchMode; +import static awais.instagrabber.utils.Utils.logCollector; + +public final class ProfilePictureFetcher extends AsyncTask { + private final FetchListener fetchListener; + private final String userName, userId; + private final ProfilePictureFetchMode fetchMode; + + public ProfilePictureFetcher(final String userName, final String userId, final FetchListener fetchListener, + final ProfilePictureFetchMode fetchMode) { + this.fetchListener = fetchListener; + this.fetchMode = fetchMode; + this.userName = userName; + this.userId = userId; + } + + @Override + protected String doInBackground(final Void... voids) { + String out = null; + try { + final String url; + + if (fetchMode == ProfilePictureFetchMode.INSTADP) + url = "https://instadp.com/fullsize/" + userName; + else if (fetchMode == ProfilePictureFetchMode.INSTA_STALKER) + url = "https://insta-stalker.co/instadp_fullsize/?id=" + userName; + else // select from s1, s2, s3 but s1 works fine + url = "https://instafullsize.com/ifsapi/ig/photo/s1/" + userName + "?igid=" + userId; + + // prolly http://167.99.85.4/instagram/userid?profile-url=the.badak + + final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setUseCaches(false); + + if (fetchMode == ProfilePictureFetchMode.INSTAFULLSIZE) { + conn.setRequestMethod("GET"); + conn.setRequestProperty("Authorization", "fjgt842ff582a"); + } + + final String result = conn.getResponseCode() == HttpURLConnection.HTTP_OK ? Utils.readFromConnection(conn) : null; + conn.disconnect(); + + if (!Utils.isEmpty(result)) { + final Document doc = Jsoup.parse(result); + boolean fallback = false; + + if (fetchMode == ProfilePictureFetchMode.INSTADP) { + final int imgIndex = result.indexOf("preloadImg('"), lastIndex; + + Element element = doc.selectFirst(".instadp"); + if (element != null && (element = element.selectFirst(".picture")) != null) + out = element.attr("src"); + else if ((element = doc.selectFirst(".download-btn")) != null) + out = element.attr("href"); + else if (imgIndex != -1 && (lastIndex = result.indexOf("')", imgIndex)) != -1) + out = result.substring(imgIndex + 12, lastIndex); + else fallback = true; + + } else if (fetchMode == ProfilePictureFetchMode.INSTAFULLSIZE) { + try { + final JSONObject object = new JSONObject(result); + out = object.getString("result"); + } catch (final Exception e) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + fallback = true; + } + + } else { + final Elements elements = doc.select("img[data-src]"); + if (elements.size() > 0) out = elements.get(0).attr("data-src"); + else fallback = true; + } + + if (fallback) { + final Elements imgs = doc.getElementsByTag("img"); + for (final Element img : imgs) { + final String imgStr = img.toString(); + if (imgStr.contains("cdninstagram.com")) return img.attr("src"); + } + } + } + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.ASYNC_PROFILE_PICTURE_FETCHER, "doInBackground", + new Pair<>("fetchMode", fetchMode)); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return out; + } + + @Override + protected void onPreExecute() { + if (fetchListener != null) fetchListener.doBefore(); + } + + @Override + protected void onPostExecute(final String result) { + if (fetchListener != null) fetchListener.onResult(result); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/asyncs/StoryStatusFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/StoryStatusFetcher.java new file mode 100755 index 00000000..fbf9030d --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/StoryStatusFetcher.java @@ -0,0 +1,102 @@ +package awais.instagrabber.asyncs; + +import android.os.AsyncTask; +import android.util.Log; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.net.HttpURLConnection; +import java.net.URL; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.models.StoryModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; +import awaisomereport.LogCollector; + +import static awais.instagrabber.utils.Utils.logCollector; + +public final class StoryStatusFetcher extends AsyncTask { + private final String id; + private final FetchListener fetchListener; + + public StoryStatusFetcher(final String id, final FetchListener fetchListener) { + this.id = id; + this.fetchListener = fetchListener; + } + + @Override + protected StoryModel[] doInBackground(final Void... voids) { + StoryModel[] result = null; + final String url = "https://www.instagram.com/graphql/query/?query_hash=52a36e788a02a3c612742ed5146f1676&variables=" + + "{\"precomposed_overlay\":false,\"reel_ids\":[\"" + id + "\"]}"; + + try { + final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setInstanceFollowRedirects(false); + conn.setUseCaches(false); + conn.connect(); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + JSONObject data = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("data"); + + JSONArray media; + if ((media = data.optJSONArray("reels_media")) != null && media.length() > 0 && + (data = media.optJSONObject(0)) != null && + (media = data.optJSONArray("items")) != null) { + + final int mediaLen = media.length(); + + final StoryModel[] models = new StoryModel[mediaLen]; + for (int i = 0; i < mediaLen; ++i) { + data = media.getJSONObject(i); + final boolean isVideo = data.getBoolean("is_video"); + + final JSONArray tappableObjects = data.optJSONArray("tappable_objects"); + final int tappableLength = tappableObjects != null ? tappableObjects.length() : 0; + + models[i] = new StoryModel(data.getString(Constants.EXTRAS_ID), + data.getString("display_url"), + isVideo ? MediaItemType.MEDIA_TYPE_VIDEO : MediaItemType.MEDIA_TYPE_IMAGE, + data.optLong("taken_at_timestamp", 0)); + + final JSONArray videoResources = data.optJSONArray("video_resources"); + if (isVideo && videoResources != null) + models[i].setVideoUrl(Utils.getHighQualityPost(videoResources, true)); + + for (int j = 0; j < tappableLength; ++j) { + JSONObject tappableObject = tappableObjects.getJSONObject(j); + if (tappableObject.optString("__typename").equals("GraphTappableFeedMedia")) { + tappableObject = tappableObject.getJSONObject("media"); + models[i].setTappableShortCode(tappableObject.getString(Constants.EXTRAS_SHORTCODE)); + break; + } + } + } + result = models; + } + } + + conn.disconnect(); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.ASYNC_STORY_STATUS_FETCHER, "doInBackground"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return result; + } + + @Override + protected void onPreExecute() { + if (fetchListener != null) fetchListener.doBefore(); + } + + @Override + protected void onPostExecute(final StoryModel[] result) { + if (fetchListener != null) fetchListener.onResult(result); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/asyncs/SuggestionsFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/SuggestionsFetcher.java new file mode 100755 index 00000000..4a599f1e --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/SuggestionsFetcher.java @@ -0,0 +1,98 @@ +package awais.instagrabber.asyncs; + +import android.os.AsyncTask; +import android.util.Log; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.InterruptedIOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.SuggestionModel; +import awais.instagrabber.models.enums.SuggestionType; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.UrlEncoder; +import awais.instagrabber.utils.Utils; + +public final class SuggestionsFetcher extends AsyncTask { + private final FetchListener fetchListener; + + public SuggestionsFetcher(final FetchListener fetchListener) { + this.fetchListener = fetchListener; + } + + @Override + protected void onPreExecute() { + if (fetchListener != null) fetchListener.doBefore(); + } + + @Override + protected SuggestionModel[] doInBackground(final String... params) { + SuggestionModel[] result = null; + try { + final HttpURLConnection conn = (HttpURLConnection) new URL("https://www.instagram.com/web/search/topsearch/?context=blended&count=50&query=" + + UrlEncoder.encodeUrl(params[0])).openConnection(); + conn.setUseCaches(false); + conn.connect(); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + final String defaultHashTagPic = "https://www.instagram.com/static/images/hashtag/search-hashtag-default-avatar.png/1d8417c9a4f5.png"; + final JSONObject jsonObject = new JSONObject(Utils.readFromConnection(conn)); + conn.disconnect(); + + final JSONArray usersArray = jsonObject.getJSONArray("users"); + final JSONArray hashtagsArray = jsonObject.getJSONArray("hashtags"); + + final int usersLen = usersArray.length(); + final int hashtagsLen = hashtagsArray.length(); + + final ArrayList suggestionModels = new ArrayList<>(usersLen + hashtagsLen); + for (int i = 0; i < hashtagsLen; i++) { + final JSONObject hashtagsArrayJSONObject = hashtagsArray.getJSONObject(i); + + final JSONObject hashtag = hashtagsArrayJSONObject.getJSONObject("hashtag"); + + suggestionModels.add(new SuggestionModel(false, + hashtag.getString(Constants.EXTRAS_NAME), + null, + hashtag.optString("profile_pic_url", defaultHashTagPic), + SuggestionType.TYPE_HASHTAG, + hashtagsArrayJSONObject.optInt("position", suggestionModels.size() - 1))); + } + + for (int i = 0; i < usersLen; i++) { + final JSONObject usersArrayJSONObject = usersArray.getJSONObject(i); + + final JSONObject user = usersArrayJSONObject.getJSONObject(Constants.EXTRAS_USER); + + suggestionModels.add(new SuggestionModel(user.getBoolean("is_verified"), + user.getString(Constants.EXTRAS_USERNAME), + user.getString("full_name"), + user.getString("profile_pic_url"), + SuggestionType.TYPE_USER, + usersArrayJSONObject.optInt("position", suggestionModels.size() - 1))); + } + + suggestionModels.trimToSize(); + + Collections.sort(suggestionModels); + + result = suggestionModels.toArray(new SuggestionModel[0]); + } + } catch (final Exception e) { + if (BuildConfig.DEBUG && !(e instanceof InterruptedIOException)) Log.e("AWAISKING_APP", "", e); + } + return result; + } + + @Override + protected void onPostExecute(final SuggestionModel[] result) { + if (fetchListener != null) fetchListener.onResult(result); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/asyncs/UsernameFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/UsernameFetcher.java new file mode 100755 index 00000000..0efff6b9 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/UsernameFetcher.java @@ -0,0 +1,54 @@ +package awais.instagrabber.asyncs; + +import android.os.AsyncTask; +import android.util.Log; + +import androidx.annotation.Nullable; + +import org.json.JSONObject; + +import java.net.HttpURLConnection; +import java.net.URL; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; + +public final class UsernameFetcher extends AsyncTask { + private final FetchListener fetchListener; + private final String uid; + + public UsernameFetcher(final String uid, final FetchListener fetchListener) { + this.uid = uid; + this.fetchListener = fetchListener; + } + + @Nullable + @Override + protected String doInBackground(final Void... voids) { + String result = null; + + try { + final HttpURLConnection conn = (HttpURLConnection) new URL("https://i.instagram.com/api/v1/users/" + uid + "/info/").openConnection(); + conn.setRequestProperty("User-Agent", Constants.USER_AGENT); + conn.setUseCaches(true); + + final JSONObject user; + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK && + (user = new JSONObject(Utils.readFromConnection(conn)).optJSONObject(Constants.EXTRAS_USER)) != null) + result = user.getString(Constants.EXTRAS_USERNAME); + + conn.disconnect(); + } catch (final Exception e) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return result; + } + + @Override + protected void onPostExecute(final String result) { + if (fetchListener != null) fetchListener.onResult(result); + } +} diff --git a/app/src/main/java/awais/instagrabber/asyncs/direct_messages/InboxFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/direct_messages/InboxFetcher.java new file mode 100755 index 00000000..0d185bcf --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/direct_messages/InboxFetcher.java @@ -0,0 +1,100 @@ +package awais.instagrabber.asyncs.direct_messages; + +import android.os.AsyncTask; +import android.util.Log; + +import androidx.annotation.Nullable; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.net.HttpURLConnection; +import java.net.URL; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.direct_messages.InboxModel; +import awais.instagrabber.models.direct_messages.InboxThreadModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.LocaleUtils; +import awais.instagrabber.utils.Utils; + +import static awais.instagrabber.utils.Utils.logCollector; +import static awaisomereport.LogCollector.LogFile; + +public final class InboxFetcher extends AsyncTask { + private final String endCursor; + private final FetchListener fetchListener; + + public InboxFetcher(final String endCursor, final FetchListener fetchListener) { + this.endCursor = Utils.isEmpty(endCursor) ? "" : "?cursor=" + endCursor; + this.fetchListener = fetchListener; + } + + @Nullable + @Override + protected InboxModel doInBackground(final Void... voids) { + InboxModel result = null; + + final String url = "https://i.instagram.com/api/v1/direct_v2/inbox/" + endCursor; + try { + final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setRequestProperty("User-Agent", Constants.USER_AGENT); + conn.setRequestProperty("Accept-Language", LocaleUtils.getCurrentLocale().getLanguage() + ",en-US;q=0.8"); + conn.setUseCaches(false); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + JSONObject data = new JSONObject(Utils.readFromConnection(conn)); + // try (FileWriter fileWriter = new FileWriter(new File("/sdcard/test.json"))) { + // fileWriter.write(data.toString(2)); + // } + + final long seqId = data.optLong("seq_id"); + final int pendingRequestsCount = data.optInt("pending_requests_total"); + final boolean hasPendingTopRequests = data.optBoolean("has_pending_top_requests"); + + data = data.getJSONObject("inbox"); + + final boolean blendedInboxEnabled = data.optBoolean("blended_inbox_enabled"); + final boolean hasOlder = data.optBoolean("has_older"); + final int unseenCount = data.optInt("unseen_count"); + final long unseenCountTimestamp = data.optLong("unseen_count_ts"); + final String oldestCursor = data.optString("oldest_cursor"); + + InboxThreadModel[] inboxThreadModels = null; + + final JSONArray threadsArray = data.optJSONArray("threads"); + if (threadsArray != null) { + final int threadsLen = threadsArray.length(); + inboxThreadModels = new InboxThreadModel[threadsLen]; + + for (int i = 0; i < threadsLen; ++i) + inboxThreadModels[i] = Utils.createInboxThreadModel(threadsArray.getJSONObject(i), false); + } + + result = new InboxModel(hasOlder, hasPendingTopRequests, + blendedInboxEnabled, unseenCount, pendingRequestsCount, + seqId, unseenCountTimestamp, oldestCursor, inboxThreadModels); + } + + conn.disconnect(); + } catch (final Exception e) { + result = null; + if (logCollector != null) + logCollector.appendException(e, LogFile.ASYNC_DMS, "doInBackground"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return result; + } + + @Override + protected void onPreExecute() { + if (fetchListener != null) fetchListener.doBefore(); + } + + @Override + protected void onPostExecute(final InboxModel inboxModel) { + if (fetchListener != null) fetchListener.onResult(inboxModel); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/asyncs/direct_messages/UserInboxFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/direct_messages/UserInboxFetcher.java new file mode 100755 index 00000000..8134aab2 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/asyncs/direct_messages/UserInboxFetcher.java @@ -0,0 +1,76 @@ +package awais.instagrabber.asyncs.direct_messages; + +import android.os.AsyncTask; +import android.util.Log; + +import androidx.annotation.Nullable; + +import org.json.JSONObject; + +import java.net.HttpURLConnection; +import java.net.URL; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.direct_messages.InboxThreadModel; +import awais.instagrabber.models.enums.UserInboxDirection; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; + +import static awais.instagrabber.utils.Utils.logCollector; +import static awaisomereport.LogCollector.LogFile; + +public final class UserInboxFetcher extends AsyncTask { + private final String id; + private final String endCursor; + private final FetchListener fetchListener; + private final String direction; + + public UserInboxFetcher(final String id, final UserInboxDirection direction, final String endCursor, + final FetchListener fetchListener) { + this.id = id; + this.direction = "&direction=" + (direction == UserInboxDirection.NEWER ? "newer" : "older"); + this.endCursor = !Utils.isEmpty(endCursor) ? "&cursor=" + endCursor : ""; + this.fetchListener = fetchListener; + } + + @Nullable + @Override + protected InboxThreadModel doInBackground(final Void... voids) { + InboxThreadModel result = null; + final String url = "https://i.instagram.com/api/v1/direct_v2/threads/" + id + "/?visual_message_return_type=unseen" + + direction + endCursor; + // todo probably + // & seq_id = seqId + + try { + final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setRequestProperty("User-Agent", Constants.USER_AGENT); + conn.setUseCaches(false); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + final JSONObject data = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("thread"); + result = Utils.createInboxThreadModel(data, true); + } + + conn.disconnect(); + } catch (final Exception e) { + result = null; + if (logCollector != null) + logCollector.appendException(e, LogFile.ASYNC_DMS_THREAD, "doInBackground"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return result; + } + + @Override + protected void onPreExecute() { + if (fetchListener != null) fetchListener.doBefore(); + } + + @Override + protected void onPostExecute(final InboxThreadModel inboxThreadModel) { + if (fetchListener != null) fetchListener.onResult(inboxThreadModel); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/customviews/CircularImageView.java b/app/src/main/java/awais/instagrabber/customviews/CircularImageView.java new file mode 100755 index 00000000..4ebffb6b --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/CircularImageView.java @@ -0,0 +1,105 @@ +package awais.instagrabber.customviews; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Outline; +import android.graphics.Paint; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.os.Build; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewOutlineProvider; + +import androidx.appcompat.widget.AppCompatImageView; + +public final class CircularImageView extends AppCompatImageView { + private final int borderSize = 8; + private int color = Color.TRANSPARENT; + private final Paint paint = new Paint(); + private final Paint paintBorder = new Paint(); + private BitmapShader shader; + private Bitmap bitmap; + + public CircularImageView(final Context context) { + super(context); + setup(); + } + + public CircularImageView(final Context context, final AttributeSet attrs) { + super(context, attrs); + setup(); + } + + public CircularImageView(final Context context, final AttributeSet attrs, final int defStyleAttr) { + super(context, attrs, defStyleAttr); + setup(); + } + + private void setup() { + paint.setAntiAlias(true); + paintBorder.setColor(color); + paintBorder.setAntiAlias(true); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + setOutlineProvider(new ViewOutlineProvider() { + private int viewHeight; + private int viewWidth; + + @Override + public void getOutline(final View view, final Outline outline) { + if (viewHeight == 0) viewHeight = getHeight(); + if (viewWidth == 0) viewWidth = getWidth(); + outline.setRoundRect(borderSize, borderSize, viewWidth - borderSize, viewHeight - borderSize, viewHeight >> 1); + } + }); + } + } + + @Override + public void onDraw(final Canvas canvas) { + final BitmapDrawable bitmapDrawable = (BitmapDrawable) getDrawable(); + if (bitmapDrawable != null) { + final Bitmap prevBitmap = bitmap; + bitmap = bitmapDrawable.getBitmap(); + final boolean changed = prevBitmap != bitmap; + if (bitmap != null) { + final int width = getWidth(); + final int height = getHeight(); + + if (shader == null || changed) { + shader = new BitmapShader(Bitmap.createScaledBitmap(bitmap, width, height, true), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + paint.setShader(shader); + } + + if (changed) color = 0; + paintBorder.setColor(color); + + final int circleCenter = (width - borderSize) / 2; + final int position = circleCenter + (borderSize / 2); + canvas.drawCircle(position, position, position - 4.0f, paintBorder); + canvas.drawCircle(position, position, circleCenter - 4.0f, paint); + } + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + setLayerType(LAYER_TYPE_HARDWARE, null); + } + + @Override + protected void onDetachedFromWindow() { + setLayerType(LAYER_TYPE_NONE, null); + super.onDetachedFromWindow(); + } + + public void setStoriesBorder() { + this.color = Color.GREEN; + invalidate(); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/customviews/CommentMentionClickSpan.java b/app/src/main/java/awais/instagrabber/customviews/CommentMentionClickSpan.java new file mode 100755 index 00000000..a68509c1 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/CommentMentionClickSpan.java @@ -0,0 +1,17 @@ +package awais.instagrabber.customviews; + +import android.text.TextPaint; +import android.text.style.ClickableSpan; +import android.view.View; + +import androidx.annotation.NonNull; + +public final class CommentMentionClickSpan extends ClickableSpan { + @Override + public void onClick(@NonNull final View widget) { } + + @Override + public void updateDrawState(@NonNull final TextPaint ds) { + ds.setColor(ds.linkColor); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/customviews/FixedImageView.java b/app/src/main/java/awais/instagrabber/customviews/FixedImageView.java new file mode 100755 index 00000000..302b1f94 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/FixedImageView.java @@ -0,0 +1,25 @@ +package awais.instagrabber.customviews; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.appcompat.widget.AppCompatImageView; + +public final class FixedImageView extends AppCompatImageView { + public FixedImageView(final Context context) { + super(context); + } + + public FixedImageView(final Context context, final AttributeSet attrs) { + super(context, attrs); + } + + public FixedImageView(final Context context, final AttributeSet attrs, final int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onMeasure(final int wMeasure, final int hMeasure) { + super.onMeasure(wMeasure, wMeasure); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/customviews/MouseDrawer.java b/app/src/main/java/awais/instagrabber/customviews/MouseDrawer.java new file mode 100755 index 00000000..8491be2e --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/MouseDrawer.java @@ -0,0 +1,986 @@ +package awais.instagrabber.customviews; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Gravity; +import android.view.InputDevice; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.IntDef; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.view.GravityCompat; +import androidx.core.view.ViewCompat; +import androidx.customview.view.AbsSavedState; +import androidx.customview.widget.ViewDragHelper; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import awais.instagrabber.BuildConfig; + +// exactly same as the LayoutDrawer with some edits +@SuppressLint("RtlHardcoded") +public class MouseDrawer extends ViewGroup { + @IntDef({ViewDragHelper.STATE_IDLE, ViewDragHelper.STATE_DRAGGING, ViewDragHelper.STATE_SETTLING}) + @Retention(RetentionPolicy.SOURCE) + private @interface State {} + + @IntDef(value = {Gravity.NO_GRAVITY, Gravity.LEFT, Gravity.RIGHT, GravityCompat.START, GravityCompat.END}, flag = true) + @Retention(RetentionPolicy.SOURCE) + public @interface EdgeGravity {} + + //////////////////////////////////////////////////////////////////////////////////// + private static final boolean CHILDREN_DISALLOW_INTERCEPT = true; + //////////////////////////////////////////////////////////////////////////////////// + private final ArrayList mNonDrawerViews = new ArrayList<>(); + private final ViewDragHelper mLeftDragger, mRightDragger; + private boolean mInLayout, mFirstLayout = true; + private float mDrawerElevation, mInitialMotionX, mInitialMotionY; + private int mDrawerState; + private List mListeners; + private Matrix mChildInvertedMatrix; + private Rect mChildHitRect; + + public interface DrawerListener { + void onDrawerSlide(final View drawerView, @EdgeGravity final int gravity, final float slideOffset); + default void onDrawerOpened(final View drawerView, @EdgeGravity final int gravity) {} + default void onDrawerClosed(final View drawerView, @EdgeGravity final int gravity) {} + default void onDrawerStateChanged() {} + } + + public MouseDrawer(@NonNull final Context context) { + this(context, null); + } + + public MouseDrawer(@NonNull final Context context, @Nullable final AttributeSet attrs) { + this(context, attrs, 0); + } + + public MouseDrawer(@NonNull final Context context, @Nullable final AttributeSet attrs, final int defStyle) { + super(context, attrs, defStyle); + setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); + + final float density = getResources().getDisplayMetrics().density; + this.mDrawerElevation = 10 * density; + + final float touchSlopSensitivity = 0.5f; // was 1.0f + final float minFlingVelocity = 400 /* dips per second */ * density; + + final ViewDragCallback mLeftCallback = new ViewDragCallback(Gravity.LEFT); + this.mLeftDragger = ViewDragHelper.create(this, touchSlopSensitivity, mLeftCallback); + this.mLeftDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT); + this.mLeftDragger.setMinVelocity(minFlingVelocity); + + final ViewDragCallback mRightCallback = new ViewDragCallback(Gravity.RIGHT); + this.mRightDragger = ViewDragHelper.create(this, touchSlopSensitivity, mRightCallback); + this.mRightDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_RIGHT); + this.mRightDragger.setMinVelocity(minFlingVelocity); + + try { + final Field edgeSizeField = ViewDragHelper.class.getDeclaredField("mEdgeSize"); + if (!edgeSizeField.isAccessible()) edgeSizeField.setAccessible(true); + final int widthPixels = getResources().getDisplayMetrics().widthPixels; // whole screen + edgeSizeField.set(this.mLeftDragger, widthPixels / 2); + edgeSizeField.set(this.mRightDragger, widthPixels / 2); + } catch (final Exception e) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + mLeftCallback.setDragger(mLeftDragger); + mRightCallback.setDragger(mRightDragger); + + setFocusableInTouchMode(true); + //setMotionEventSplittingEnabled(false); + } + + public void setDrawerElevation(final float elevation) { + mDrawerElevation = elevation; + for (int i = 0; i < getChildCount(); i++) { + final View child = getChildAt(i); + if (isDrawerView(child)) ViewCompat.setElevation(child, mDrawerElevation); + } + } + + public float getDrawerElevation() { + return Build.VERSION.SDK_INT >= 21 ? mDrawerElevation : 0f; + } + + public void addDrawerListener(@NonNull final DrawerListener listener) { + if (mListeners == null) mListeners = new ArrayList<>(); + mListeners.add(listener); + } + + private boolean isInBoundsOfChild(final float x, final float y, final View child) { + if (mChildHitRect == null) mChildHitRect = new Rect(); + child.getHitRect(mChildHitRect); + return mChildHitRect.contains((int) x, (int) y); + } + + private boolean dispatchTransformedGenericPointerEvent(final MotionEvent event, @NonNull final View child) { + final boolean handled; + final Matrix childMatrix = child.getMatrix(); + if (!childMatrix.isIdentity()) { + final MotionEvent transformedEvent = getTransformedMotionEvent(event, child); + handled = child.dispatchGenericMotionEvent(transformedEvent); + transformedEvent.recycle(); + } else { + final float offsetX = getScrollX() - child.getLeft(); + final float offsetY = getScrollY() - child.getTop(); + event.offsetLocation(offsetX, offsetY); + handled = child.dispatchGenericMotionEvent(event); + event.offsetLocation(-offsetX, -offsetY); + } + return handled; + } + + @NonNull + private MotionEvent getTransformedMotionEvent(final MotionEvent event, @NonNull final View child) { + final float offsetX = getScrollX() - child.getLeft(); + final float offsetY = getScrollY() - child.getTop(); + final MotionEvent transformedEvent = MotionEvent.obtain(event); + transformedEvent.offsetLocation(offsetX, offsetY); + final Matrix childMatrix = child.getMatrix(); + if (!childMatrix.isIdentity()) { + if (mChildInvertedMatrix == null) mChildInvertedMatrix = new Matrix(); + childMatrix.invert(mChildInvertedMatrix); + transformedEvent.transform(mChildInvertedMatrix); + } + return transformedEvent; + } + + void updateDrawerState(@State final int activeState, final View activeDrawer) { + final int leftState = mLeftDragger.getViewDragState(); + final int rightState = mRightDragger.getViewDragState(); + + final int state; + if (leftState == ViewDragHelper.STATE_DRAGGING || rightState == ViewDragHelper.STATE_DRAGGING) + state = ViewDragHelper.STATE_DRAGGING; + else if (leftState == ViewDragHelper.STATE_SETTLING || rightState == ViewDragHelper.STATE_SETTLING) + state = ViewDragHelper.STATE_SETTLING; + else state = ViewDragHelper.STATE_IDLE; + + if (activeDrawer != null && activeState == ViewDragHelper.STATE_IDLE) { + final LayoutParams lp = (LayoutParams) activeDrawer.getLayoutParams(); + if (lp.onScreen == 0) dispatchOnDrawerClosed(activeDrawer); + else if (lp.onScreen == 1) dispatchOnDrawerOpened(activeDrawer); + } + + if (state != mDrawerState) { + mDrawerState = state; + + if (mListeners != null) { + final int listenerCount = mListeners.size(); + for (int i = listenerCount - 1; i >= 0; i--) mListeners.get(i).onDrawerStateChanged(); + } + } + } + + void dispatchOnDrawerClosed(@NonNull final View drawerView) { + final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams(); + if ((lp.openState & LayoutParams.FLAG_IS_OPENED) == 1) { + lp.openState = 0; + + if (mListeners != null) { + final int listenerCount = mListeners.size(); + for (int i = listenerCount - 1; i >= 0; i--) mListeners.get(i).onDrawerClosed(drawerView, lp.gravity); + } + } + } + + void dispatchOnDrawerOpened(@NonNull final View drawerView) { + final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams(); + if ((lp.openState & LayoutParams.FLAG_IS_OPENED) == 0) { + lp.openState = LayoutParams.FLAG_IS_OPENED; + if (mListeners != null) { + final int listenerCount = mListeners.size(); + for (int i = listenerCount - 1; i >= 0; i--) mListeners.get(i).onDrawerOpened(drawerView, lp.gravity); + } + } + } + + void setDrawerViewOffset(@NonNull final View drawerView, final float slideOffset) { + final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams(); + if (slideOffset != lp.onScreen) { + lp.onScreen = slideOffset; + + if (mListeners != null) { + final int listenerCount = mListeners.size(); + for (int i = listenerCount - 1; i >= 0; i--) + mListeners.get(i).onDrawerSlide(drawerView, lp.gravity, slideOffset); + } + } + } + + float getDrawerViewOffset(@NonNull final View drawerView) { + return ((LayoutParams) drawerView.getLayoutParams()).onScreen; + } + + int getDrawerViewAbsoluteGravity(@NonNull final View drawerView) { + final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity; + return GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(this)); + } + + boolean checkDrawerViewAbsoluteGravity(final View drawerView, final int checkFor) { + final int absGravity = getDrawerViewAbsoluteGravity(drawerView); + return (absGravity & checkFor) == checkFor; + } + + void moveDrawerToOffset(final View drawerView, final float slideOffset) { + final float oldOffset = getDrawerViewOffset(drawerView); + final int width = drawerView.getWidth(); + final int oldPos = (int) (width * oldOffset); + final int newPos = (int) (width * slideOffset); + final int dx = newPos - oldPos; + + drawerView.offsetLeftAndRight(checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT) ? dx : -dx); + setDrawerViewOffset(drawerView, slideOffset); + } + + public View findOpenDrawer() { + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams childLp = (LayoutParams) child.getLayoutParams(); + if ((childLp.openState & LayoutParams.FLAG_IS_OPENED) == 1) return child; + } + return null; + } + + public View findDrawerWithGravity(final int gravity) { + final int absHorizGravity = GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(this)) & Gravity.HORIZONTAL_GRAVITY_MASK; + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final int childAbsGravity = getDrawerViewAbsoluteGravity(child); + if ((childAbsGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == absHorizGravity) return child; + } + return null; + } + + @NonNull + static String gravityToString(@EdgeGravity final int gravity) { + if ((gravity & Gravity.LEFT) == Gravity.LEFT) return "LEFT"; + if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) return "RIGHT"; + return Integer.toHexString(gravity); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mFirstLayout = true; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mFirstLayout = true; + } + + @SuppressLint("WrongConstant") + @Override + protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { + final int widthSize = MeasureSpec.getSize(widthMeasureSpec); + final int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + setMeasuredDimension(widthSize, heightSize); + + boolean hasDrawerOnLeftEdge = false; + boolean hasDrawerOnRightEdge = false; + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + if (isContentView(child)) { + // Content views get measured at exactly the layout's size. + final int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize - lp.leftMargin - lp.rightMargin, MeasureSpec.EXACTLY); + final int contentHeightSpec = MeasureSpec.makeMeasureSpec(heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY); + child.measure(contentWidthSpec, contentHeightSpec); + + } else if (isDrawerView(child)) { + if (Build.VERSION.SDK_INT >= 21 && ViewCompat.getElevation(child) != mDrawerElevation) + ViewCompat.setElevation(child, mDrawerElevation); + final int childGravity = getDrawerViewAbsoluteGravity(child) & Gravity.HORIZONTAL_GRAVITY_MASK; + + final boolean isLeftEdgeDrawer = (childGravity == Gravity.LEFT); + if (isLeftEdgeDrawer && hasDrawerOnLeftEdge || !isLeftEdgeDrawer && hasDrawerOnRightEdge) + throw new IllegalStateException("Child drawer has absolute gravity " + gravityToString(childGravity) + + " but this MouseDrawer already has a drawer view along that edge"); + + if (isLeftEdgeDrawer) hasDrawerOnLeftEdge = true; + else hasDrawerOnRightEdge = true; + + final int drawerWidthSpec = getChildMeasureSpec(widthMeasureSpec, lp.leftMargin + lp.rightMargin, lp.width); + final int drawerHeightSpec = getChildMeasureSpec(heightMeasureSpec, lp.topMargin + lp.bottomMargin, lp.height); + child.measure(drawerWidthSpec, drawerHeightSpec); + } else + throw new IllegalStateException("Child " + child + " at index " + i + + " does not have a valid layout_gravity - must be Gravity.LEFT, Gravity.RIGHT or Gravity.NO_GRAVITY"); + } + } + } + + @Override + protected void onLayout(final boolean changed, final int left, final int top, final int right, final int bottom) { + mInLayout = true; + final int width = right - left; + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + if (isContentView(child)) { + child.layout(lp.leftMargin, lp.topMargin, lp.leftMargin + child.getMeasuredWidth(), + lp.topMargin + child.getMeasuredHeight()); + + } else { // Drawer, if it wasn't onMeasure would have thrown an exception. + final int childWidth = child.getMeasuredWidth(); + final int childHeight = child.getMeasuredHeight(); + final int childLeft; + final float newOffset; + + if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) { + childLeft = -childWidth + (int) (childWidth * lp.onScreen); + newOffset = (float) (childWidth + childLeft) / childWidth; + } else { // Right; onMeasure checked for us. + childLeft = width - (int) (childWidth * lp.onScreen); + newOffset = (float) (width - childLeft) / childWidth; + } + + final boolean changeOffset = newOffset != lp.onScreen; + + final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; + switch (vgrav) { + default: + case Gravity.TOP: + child.layout(childLeft, lp.topMargin, childLeft + childWidth, lp.topMargin + childHeight); + break; + + case Gravity.BOTTOM: { + final int height = bottom - top; + child.layout(childLeft, height - lp.bottomMargin - child.getMeasuredHeight(), + childLeft + childWidth, height - lp.bottomMargin); + break; + } + + case Gravity.CENTER_VERTICAL: { + final int height = bottom - top; + int childTop = (height - childHeight) / 2; + + if (childTop < lp.topMargin) childTop = lp.topMargin; + else if (childTop + childHeight > height - lp.bottomMargin) + childTop = height - lp.bottomMargin - childHeight; + + child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight); + break; + } + } + + if (changeOffset) setDrawerViewOffset(child, newOffset); + + final int newVisibility = lp.onScreen > 0 ? VISIBLE : INVISIBLE; + if (child.getVisibility() != newVisibility) child.setVisibility(newVisibility); + } + } + } + mInLayout = false; + mFirstLayout = false; + } + + @Override + public void requestLayout() { + if (!mInLayout) super.requestLayout(); + } + + @Override + public void computeScroll() { + final boolean leftDraggerSettling = mLeftDragger.continueSettling(true); + final boolean rightDraggerSettling = mRightDragger.continueSettling(true); + if (leftDraggerSettling || rightDraggerSettling) postInvalidateOnAnimation(); + } + + private static boolean hasOpaqueBackground(@NonNull final View v) { + final Drawable bg = v.getBackground(); + if (bg != null) return bg.getOpacity() == PixelFormat.OPAQUE; + return false; + } + + @Override + protected boolean drawChild(@NonNull final Canvas canvas, final View child, final long drawingTime) { + final int height = getHeight(); + final boolean drawingContent = isContentView(child); + int clipLeft = 0, clipRight = getWidth(); + + final int restoreCount = canvas.save(); + if (drawingContent) { + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View v = getChildAt(i); + if (v != child && v.getVisibility() == VISIBLE && hasOpaqueBackground(v) && isDrawerView(v) && v.getHeight() >= height) { + if (checkDrawerViewAbsoluteGravity(v, Gravity.LEFT)) { + final int vright = v.getRight(); + if (vright > clipLeft) clipLeft = vright; + } else { + final int vleft = v.getLeft(); + if (vleft < clipRight) clipRight = vleft; + } + } + } + canvas.clipRect(clipLeft, 0, clipRight, getHeight()); + } + + final boolean result = super.drawChild(canvas, child, drawingTime); + canvas.restoreToCount(restoreCount); + + return result; + } + + boolean isContentView(@NonNull final View child) { + return ((LayoutParams) child.getLayoutParams()).gravity == Gravity.NO_GRAVITY; + } + + boolean isDrawerView(@NonNull final View child) { + final int gravity = ((LayoutParams) child.getLayoutParams()).gravity; + final int absGravity = GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(child)); + return (absGravity & Gravity.LEFT) != 0 || (absGravity & Gravity.RIGHT) != 0; + } + + @Override + public boolean onInterceptTouchEvent(@NonNull final MotionEvent ev) { + final int action = ev.getActionMasked(); + + // "|" used deliberately here; both methods should be invoked. + final boolean interceptForDrag = mLeftDragger.shouldInterceptTouchEvent(ev) | mRightDragger.shouldInterceptTouchEvent(ev); + + switch (action) { + case MotionEvent.ACTION_DOWN: + mInitialMotionX = ev.getX(); + mInitialMotionY = ev.getY(); + break; + + case MotionEvent.ACTION_MOVE: + mLeftDragger.checkTouchSlop(ViewDragHelper.DIRECTION_ALL); + break; + + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + closeDrawers(true); + } + + return interceptForDrag || hasPeekingDrawer(); + } + + @Override + public boolean dispatchGenericMotionEvent(@NonNull final MotionEvent event) { + if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0 || event.getAction() == MotionEvent.ACTION_HOVER_EXIT) + return super.dispatchGenericMotionEvent(event); + + final int childrenCount = getChildCount(); + if (childrenCount != 0) { + final float x = event.getX(); + final float y = event.getY(); + + // Walk through children from top to bottom. + for (int i = childrenCount - 1; i >= 0; i--) { + final View child = getChildAt(i); + if (isInBoundsOfChild(x, y, child) && !isContentView(child) && dispatchTransformedGenericPointerEvent(event, child)) + return true; + } + } + + return false; + } + + @SuppressLint("ClickableViewAccessibility") + @Override + public boolean onTouchEvent(final MotionEvent ev) { + mLeftDragger.processTouchEvent(ev); + mRightDragger.processTouchEvent(ev); + + final int action = ev.getActionMasked(); + switch (action) { + case MotionEvent.ACTION_DOWN: + mInitialMotionX = ev.getX(); + mInitialMotionY = ev.getY(); + break; + + case MotionEvent.ACTION_UP: + final float x = ev.getX(); + final float y = ev.getY(); + + boolean peekingOnly = true; + final View touchedView = mLeftDragger.findTopChildUnder((int) x, (int) y); + if (touchedView != null && isContentView(touchedView)) { + final float dx = x - mInitialMotionX; + final float dy = y - mInitialMotionY; + final int slop = mLeftDragger.getTouchSlop(); + if (dx * dx + dy * dy < slop * slop) { + // Taps close a dimmed open drawer but only if it isn't locked open. + final View openDrawer = findOpenDrawer(); + if (openDrawer != null) peekingOnly = false; + } + } + closeDrawers(peekingOnly); + break; + + case MotionEvent.ACTION_CANCEL: + closeDrawers(true); + break; + } + + return true; + } + + @Override + public void requestDisallowInterceptTouchEvent(final boolean disallowIntercept) { + if (CHILDREN_DISALLOW_INTERCEPT || (!mLeftDragger.isEdgeTouched(ViewDragHelper.EDGE_LEFT) && !mRightDragger.isEdgeTouched(ViewDragHelper.EDGE_RIGHT))) + super.requestDisallowInterceptTouchEvent(disallowIntercept); + if (disallowIntercept) closeDrawers(true); + } + + public void closeDrawers() { + closeDrawers(false); + } + + void closeDrawers(final boolean peekingOnly) { + boolean needsInvalidate = false; + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + if (isDrawerView(child) && (!peekingOnly || lp.isPeeking)) { + final int childWidth = child.getWidth(); + + if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) + needsInvalidate |= mLeftDragger.smoothSlideViewTo(child, -childWidth, child.getTop()); + else + needsInvalidate |= mRightDragger.smoothSlideViewTo(child, getWidth(), child.getTop()); + + lp.isPeeking = false; + } + } + + if (needsInvalidate) invalidate(); + } + + public void openDrawer(@NonNull final View drawerView, final boolean animate) { + if (isDrawerView(drawerView)) { + final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams(); + + if (mFirstLayout) { + lp.onScreen = 1.f; + lp.openState = LayoutParams.FLAG_IS_OPENED; + } else if (animate) { + lp.openState |= LayoutParams.FLAG_IS_OPENING; + + if (checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT)) + mLeftDragger.smoothSlideViewTo(drawerView, 0, drawerView.getTop()); + else + mRightDragger.smoothSlideViewTo(drawerView, getWidth() - drawerView.getWidth(), drawerView.getTop()); + } else { + moveDrawerToOffset(drawerView, 1.f); + updateDrawerState(ViewDragHelper.STATE_IDLE, drawerView); + drawerView.setVisibility(VISIBLE); + } + + invalidate(); + return; + } + throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer"); + } + + public void openDrawer(@NonNull final View drawerView) { + openDrawer(drawerView, true); + } + + // public void openDrawer(@EdgeGravity final int gravity, final boolean animate) { + // final View drawerView = findDrawerWithGravity(gravity); + // if (drawerView != null) openDrawer(drawerView, animate); + // else throw new IllegalArgumentException("No drawer view found with gravity " + gravityToString(gravity)); + // } + + // public void openDrawer(@EdgeGravity final int gravity) { + // openDrawer(gravity, true); + // } + + public void closeDrawer(@NonNull final View drawerView) { + closeDrawer(drawerView, true); + } + + public void closeDrawer(@NonNull final View drawerView, final boolean animate) { + if (isDrawerView(drawerView)) { + final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams(); + if (mFirstLayout) { + lp.onScreen = 0.f; + lp.openState = 0; + } else if (animate) { + lp.openState |= LayoutParams.FLAG_IS_CLOSING; + + if (checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT)) + mLeftDragger.smoothSlideViewTo(drawerView, -drawerView.getWidth(), drawerView.getTop()); + else + mRightDragger.smoothSlideViewTo(drawerView, getWidth(), drawerView.getTop()); + } else { + moveDrawerToOffset(drawerView, 0.f); + updateDrawerState(ViewDragHelper.STATE_IDLE, drawerView); + drawerView.setVisibility(INVISIBLE); + } + invalidate(); + } else throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer"); + } + + // public void closeDrawer(@EdgeGravity final int gravity) { + // closeDrawer(gravity, true); + // } + + // public void closeDrawer(@EdgeGravity final int gravity, final boolean animate) { + // final View drawerView = findDrawerWithGravity(gravity); + // if (drawerView != null) closeDrawer(drawerView, animate); + // else throw new IllegalArgumentException("No drawer view found with gravity " + gravityToString(gravity)); + // } + + public boolean isDrawerOpen(@NonNull final View drawer) { + if (isDrawerView(drawer)) return (((LayoutParams) drawer.getLayoutParams()).openState & LayoutParams.FLAG_IS_OPENED) == 1; + else throw new IllegalArgumentException("View " + drawer + " is not a drawer"); + } + + // public boolean isDrawerOpen(@EdgeGravity final int drawerGravity) { + // final View drawerView = findDrawerWithGravity(drawerGravity); + // return drawerView != null && isDrawerOpen(drawerView); + // } + + public boolean isDrawerVisible(@NonNull final View drawer) { + if (isDrawerView(drawer)) return ((LayoutParams) drawer.getLayoutParams()).onScreen > 0; + throw new IllegalArgumentException("View " + drawer + " is not a drawer"); + } + + // public boolean isDrawerVisible(@EdgeGravity final int drawerGravity) { + // final View drawerView = findDrawerWithGravity(drawerGravity); + // return drawerView != null && isDrawerVisible(drawerView); + // } + + private boolean hasPeekingDrawer() { + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams(); + if (lp.isPeeking) return true; + } + return false; + } + + @Override + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + } + + @Override + protected ViewGroup.LayoutParams generateLayoutParams(final ViewGroup.LayoutParams params) { + return params instanceof LayoutParams ? new LayoutParams((LayoutParams) params) : + params instanceof ViewGroup.MarginLayoutParams ? new LayoutParams((MarginLayoutParams) params) : new LayoutParams(params); + } + + @Override + protected boolean checkLayoutParams(final ViewGroup.LayoutParams params) { + return params instanceof LayoutParams && super.checkLayoutParams(params); + } + + @Override + public ViewGroup.LayoutParams generateLayoutParams(final AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + @Override + public void addFocusables(final ArrayList views, final int direction, final int focusableMode) { + if (getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS) { + final int childCount = getChildCount(); + boolean isDrawerOpen = false; + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + if (!isDrawerView(child)) mNonDrawerViews.add(child); + else if (isDrawerOpen(child)) { + isDrawerOpen = true; + child.addFocusables(views, direction, focusableMode); + } + } + + if (!isDrawerOpen) { + final int nonDrawerViewsCount = mNonDrawerViews.size(); + for (int i = 0; i < nonDrawerViewsCount; ++i) { + final View child = mNonDrawerViews.get(i); + if (child.getVisibility() == View.VISIBLE) child.addFocusables(views, direction, focusableMode); + } + } + + mNonDrawerViews.clear(); + } + } + + private boolean hasVisibleDrawer() { + return findVisibleDrawer() != null; + } + + @Nullable + final View findVisibleDrawer() { + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + if (isDrawerView(child) && isDrawerVisible(child)) return child; + } + return null; + } + + @Override + public boolean onKeyDown(final int keyCode, final KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && hasVisibleDrawer()) { + event.startTracking(); + return true; + } + return super.onKeyDown(keyCode, event); + } + + @Override + public boolean onKeyUp(final int keyCode, final KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + final View visibleDrawer = findVisibleDrawer(); + if (visibleDrawer != null && isDrawerView(visibleDrawer)) closeDrawers(); + return visibleDrawer != null; + } + return super.onKeyUp(keyCode, event); + } + + @Override + protected void onRestoreInstanceState(final Parcelable state) { + if (state instanceof SavedState) { + final SavedState ss = (SavedState) state; + super.onRestoreInstanceState(ss.getSuperState()); + + if (ss.openDrawerGravity != Gravity.NO_GRAVITY) { + final View toOpen = findDrawerWithGravity(ss.openDrawerGravity); + if (toOpen != null) openDrawer(toOpen); + } + } else super.onRestoreInstanceState(state); + } + + @Override + protected Parcelable onSaveInstanceState() { + final Parcelable superState = super.onSaveInstanceState(); + assert superState != null; + final SavedState ss = new SavedState(superState); + + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + // Is the current child fully opened (that is, not closing)? + final boolean isOpenedAndNotClosing = (lp.openState == LayoutParams.FLAG_IS_OPENED); + // Is the current child opening? + final boolean isClosedAndOpening = (lp.openState == LayoutParams.FLAG_IS_OPENING); + if (isOpenedAndNotClosing || isClosedAndOpening) { + // If one of the conditions above holds, save the child's gravity so that we open that child during state restore. + ss.openDrawerGravity = lp.gravity; + break; + } + } + + return ss; + } + + @Override + public void addView(final View child, final int index, final ViewGroup.LayoutParams params) { + super.addView(child, index, params); + final View openDrawer = findOpenDrawer(); + if (openDrawer == null) isDrawerView(child); + } + + protected static class SavedState extends AbsSavedState { + public static final Creator CREATOR = new ClassLoaderCreator() { + @NonNull + @Override + public SavedState createFromParcel(final Parcel in, final ClassLoader loader) { + return new SavedState(in, loader); + } + + @NonNull + @Override + public SavedState createFromParcel(final Parcel in) { + return new SavedState(in, null); + } + + @NonNull + @Override + public SavedState[] newArray(final int size) { + return new SavedState[size]; + } + }; + int openDrawerGravity = Gravity.NO_GRAVITY; + + public SavedState(@NonNull final Parcelable superState) { + super(superState); + } + + public SavedState(@NonNull final Parcel in, @Nullable final ClassLoader loader) { + super(in, loader); + openDrawerGravity = in.readInt(); + } + + @Override + public void writeToParcel(final Parcel dest, final int flags) { + super.writeToParcel(dest, flags); + dest.writeInt(openDrawerGravity); + } + } + + private class ViewDragCallback extends ViewDragHelper.Callback { + private final int mAbsGravity; + private ViewDragHelper mDragger; + + ViewDragCallback(final int gravity) { + mAbsGravity = gravity; + } + + public void setDragger(final ViewDragHelper dragger) { + mDragger = dragger; + } + + @Override + public boolean tryCaptureView(@NonNull final View child, final int pointerId) { + return isDrawerView(child) && checkDrawerViewAbsoluteGravity(child, mAbsGravity); + } + + @Override + public void onViewDragStateChanged(final int state) { + updateDrawerState(state, mDragger.getCapturedView()); + } + + @Override + public void onViewPositionChanged(@NonNull final View changedView, final int left, final int top, final int dx, final int dy) { + final float offset; + final int childWidth = changedView.getWidth(); + + if (checkDrawerViewAbsoluteGravity(changedView, Gravity.LEFT)) offset = (float) (childWidth + left) / childWidth; + else offset = (float) (getWidth() - left) / childWidth; + + setDrawerViewOffset(changedView, offset); + changedView.setVisibility(offset == 0 ? INVISIBLE : VISIBLE); + invalidate(); + } + + @Override + public void onViewCaptured(@NonNull final View capturedChild, final int activePointerId) { + final LayoutParams lp = (LayoutParams) capturedChild.getLayoutParams(); + lp.isPeeking = false; + closeOtherDrawer(); + } + + private void closeOtherDrawer() { + final int otherGrav = mAbsGravity == Gravity.LEFT ? Gravity.RIGHT : Gravity.LEFT; + final View toClose = findDrawerWithGravity(otherGrav); + if (toClose != null) closeDrawer(toClose); + } + + @Override + public void onViewReleased(@NonNull final View releasedChild, final float xvel, final float yvel) { + final float offset = getDrawerViewOffset(releasedChild); + final int childWidth = releasedChild.getWidth(); + + final int left; + if (checkDrawerViewAbsoluteGravity(releasedChild, Gravity.LEFT)) + left = xvel > 0 || (xvel == 0 && offset > 0.5f) ? 0 : -childWidth; + else { + final int width = getWidth(); + left = xvel < 0 || (xvel == 0 && offset > 0.5f) ? width - childWidth : width; + } + + mDragger.settleCapturedViewAt(left, releasedChild.getTop()); + invalidate(); + } + + @Override + public void onEdgeDragStarted(final int edgeFlags, final int pointerId) { + final View toCapture; + if ((edgeFlags & ViewDragHelper.EDGE_LEFT) == ViewDragHelper.EDGE_LEFT) + toCapture = findDrawerWithGravity(Gravity.LEFT); + else toCapture = findDrawerWithGravity(Gravity.RIGHT); + + if (toCapture != null && isDrawerView(toCapture)) mDragger.captureChildView(toCapture, pointerId); + } + + @Override + public int getViewHorizontalDragRange(@NonNull final View child) { + return isDrawerView(child) ? child.getWidth() : 0; + } + + @Override + public int clampViewPositionHorizontal(@NonNull final View child, final int left, final int dx) { + if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) return Math.max(-child.getWidth(), Math.min(left, 0)); + final int width = getWidth(); + return Math.max(width - child.getWidth(), Math.min(left, width)); + } + + @Override + public int clampViewPositionVertical(@NonNull final View child, final int top, final int dy) { + return child.getTop(); + } + } + + public static class LayoutParams extends ViewGroup.MarginLayoutParams { + private static final int FLAG_IS_CLOSING = 0x4; + public static final int FLAG_IS_OPENED = 0x1; + public static final int FLAG_IS_OPENING = 0x2; + public int openState; + @EdgeGravity + public int gravity = Gravity.NO_GRAVITY; + public boolean isPeeking; + public float onScreen; + + public LayoutParams(@NonNull final Context c, @Nullable final AttributeSet attrs) { + super(c, attrs); + final TypedArray a = c.obtainStyledAttributes(attrs, new int[]{android.R.attr.layout_gravity}); + try { + this.gravity = a.getInt(0, Gravity.NO_GRAVITY); + } finally { + a.recycle(); + } + } + + public LayoutParams(final int width, final int height) { + super(width, height); + } + + public LayoutParams(@NonNull final LayoutParams source) { + super(source); + this.gravity = source.gravity; + } + + public LayoutParams(@NonNull final ViewGroup.LayoutParams source) { + super(source); + } + + public LayoutParams(@NonNull final ViewGroup.MarginLayoutParams source) { + super(source); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/customviews/RamboTextView.java b/app/src/main/java/awais/instagrabber/customviews/RamboTextView.java new file mode 100755 index 00000000..93ea7cf0 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/RamboTextView.java @@ -0,0 +1,179 @@ +package awais.instagrabber.customviews; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.RectF; +import android.text.Layout; +import android.text.Selection; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.style.BackgroundColorSpan; +import android.text.style.ClickableSpan; +import android.text.style.URLSpan; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatTextView; + +import awais.instagrabber.R; +import awais.instagrabber.interfaces.MentionClickListener; +import awais.instagrabber.models.FeedModel; +import awais.instagrabber.utils.Utils; + +public final class RamboTextView extends AppCompatTextView { + private static final int highlightBackgroundSpanKey = R.id.tvComment; + private static final RectF touchedLineBounds = new RectF(); + private ClickableSpan clickableSpanUnderTouchOnActionDown; + private MentionClickListener mentionClickListener; + private boolean isUrlHighlighted, isExpandable, isExpanded; + + public RamboTextView(final Context context) { + super(context); + } + + public RamboTextView(final Context context, final AttributeSet attrs) { + super(context, attrs); + } + + public RamboTextView(final Context context, final AttributeSet attrs, final int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public void setMentionClickListener(final MentionClickListener mentionClickListener) { + this.mentionClickListener = mentionClickListener; + } + + public void setCaptionIsExpandable(final boolean isExpandable) { + this.isExpandable = isExpandable; + } + + public void setCaptionIsExpanded(final boolean isExpanded) { + this.isExpanded = isExpanded; + } + + @SuppressLint("ClickableViewAccessibility") + @Override + public boolean onTouchEvent(final MotionEvent event) { + final CharSequence text = getText(); + if (text instanceof SpannableString || text instanceof SpannableStringBuilder) { + final Spannable spanText = (Spannable) text; + final ClickableSpan clickableSpanUnderTouch = findClickableSpanUnderTouch(this, spanText, event); + + final int action = event.getAction(); + + if (action == MotionEvent.ACTION_DOWN) clickableSpanUnderTouchOnActionDown = clickableSpanUnderTouch; + final boolean touchStartedOverAClickableSpan = clickableSpanUnderTouchOnActionDown != null; + final boolean isURLSpan = clickableSpanUnderTouch instanceof URLSpan; + + // feed view caption hacks + if (isExpandable && !touchStartedOverAClickableSpan) + return !isExpanded | super.onTouchEvent(event); // short operator, because we want two shits to work + + final Object tag = getTag(); + final FeedModel feedModel = tag instanceof FeedModel ? (FeedModel) tag : null; + + switch (action) { + case MotionEvent.ACTION_DOWN: + if (feedModel != null) feedModel.setMentionClicked(false); + if (clickableSpanUnderTouch != null) highlightUrl(clickableSpanUnderTouch, spanText); + return isURLSpan ? super.onTouchEvent(event) : touchStartedOverAClickableSpan; + + case MotionEvent.ACTION_UP: + if (touchStartedOverAClickableSpan && clickableSpanUnderTouch == clickableSpanUnderTouchOnActionDown) { + dispatchUrlClick(spanText, clickableSpanUnderTouch); + if (feedModel != null) feedModel.setMentionClicked(true); + } + cleanupOnTouchUp(spanText); + return isURLSpan ? super.onTouchEvent(event) : touchStartedOverAClickableSpan; + + case MotionEvent.ACTION_MOVE: + if (feedModel != null) feedModel.setMentionClicked(false); + if (clickableSpanUnderTouch != null) highlightUrl(clickableSpanUnderTouch, spanText); + else removeUrlHighlightColor(spanText); + return isURLSpan ? super.onTouchEvent(event) : touchStartedOverAClickableSpan; + + case MotionEvent.ACTION_CANCEL: + if (feedModel != null) feedModel.setMentionClicked(false); + cleanupOnTouchUp(spanText); + return super.onTouchEvent(event); + } + } + + return super.onTouchEvent(event); + } + + protected void dispatchUrlClick(final Spanned s, final ClickableSpan clickableSpan) { + if (mentionClickListener != null) { + final int spanStart = s.getSpanStart(clickableSpan); + final boolean ishHashtag = s.charAt(spanStart) == '#'; + + final int start = ishHashtag || s.charAt(spanStart) != '@' ? spanStart : spanStart + 1; + + CharSequence subSequence = s.subSequence(start, s.getSpanEnd(clickableSpan)); + + // for feed ellipsize + final int indexOfEllipsize = Utils.indexOfChar(subSequence, '…', 0); + if (indexOfEllipsize != -1) + subSequence = subSequence.subSequence(0, indexOfEllipsize - 1); + + mentionClickListener.onClick(this, subSequence.toString(), ishHashtag); + } + } + + protected void highlightUrl(final ClickableSpan clickableSpan, final Spannable text) { + if (!isUrlHighlighted) { + isUrlHighlighted = true; + + final int spanStart = text.getSpanStart(clickableSpan); + final int spanEnd = text.getSpanEnd(clickableSpan); + final BackgroundColorSpan highlightSpan = new BackgroundColorSpan(getHighlightColor()); + text.setSpan(highlightSpan, spanStart, spanEnd, Spannable.SPAN_INCLUSIVE_INCLUSIVE); + setTag(highlightBackgroundSpanKey, highlightSpan); + Selection.setSelection(text, spanStart, spanEnd); + } + } + + protected void removeUrlHighlightColor(final Spannable text) { + if (isUrlHighlighted) { + isUrlHighlighted = false; + + final BackgroundColorSpan highlightSpan = (BackgroundColorSpan) getTag(highlightBackgroundSpanKey); + text.removeSpan(highlightSpan); + + Selection.removeSelection(text); + } + } + + private void cleanupOnTouchUp(final Spannable text) { + clickableSpanUnderTouchOnActionDown = null; + removeUrlHighlightColor(text); + } + + @Nullable + private static ClickableSpan findClickableSpanUnderTouch(@NonNull final TextView textView, final Spannable text, @NonNull final MotionEvent event) { + final int touchX = (int) (event.getX() - textView.getTotalPaddingLeft() + textView.getScrollX()); + final int touchY = (int) (event.getY() - textView.getTotalPaddingTop() + textView.getScrollY()); + + final Layout layout = textView.getLayout(); + final int touchedLine = layout.getLineForVertical(touchY); + final int touchOffset = layout.getOffsetForHorizontal(touchedLine, touchX); + + touchedLineBounds.left = layout.getLineLeft(touchedLine); + touchedLineBounds.top = layout.getLineTop(touchedLine); + touchedLineBounds.right = layout.getLineWidth(touchedLine) + touchedLineBounds.left; + touchedLineBounds.bottom = layout.getLineBottom(touchedLine); + + if (touchedLineBounds.contains(touchX, touchY)) { + final Object[] spans = text.getSpans(touchOffset, touchOffset, ClickableSpan.class); + for (final Object span : spans) + if (span instanceof ClickableSpan) return (ClickableSpan) span; + } + + return null; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/customviews/RemixDrawerLayout.java b/app/src/main/java/awais/instagrabber/customviews/RemixDrawerLayout.java new file mode 100755 index 00000000..e41ac94d --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/RemixDrawerLayout.java @@ -0,0 +1,182 @@ +package awais.instagrabber.customviews; + +import android.app.Activity; +import android.content.Context; +import android.content.ContextWrapper; +import android.content.res.Configuration; +import android.graphics.Rect; +import android.os.Build; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.FrameLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.view.GravityCompat; +import androidx.core.view.ViewCompat; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import awais.instagrabber.R; + +public final class RemixDrawerLayout extends MouseDrawer implements MouseDrawer.DrawerListener { + private final FrameLayout frameLayout; + private View drawerView; + private RecyclerView scroll, feedPosts; + private float startX; + + public RemixDrawerLayout(@NonNull final Context context) { + this(context, null); + } + + public RemixDrawerLayout(@NonNull final Context context, @Nullable final AttributeSet attrs) { + this(context, attrs, 0); + } + + public RemixDrawerLayout(@NonNull final Context context, @Nullable final AttributeSet attrs, final int defStyle) { + super(context, attrs, defStyle); + + super.setDrawerElevation(getDrawerElevation()); + + addDrawerListener(this); + + frameLayout = new FrameLayout(context); + frameLayout.setPadding(0, 0, 0, 0); + super.addView(frameLayout); + } + + @Override + public void addView(@NonNull final View child, final ViewGroup.LayoutParams params) { + child.setLayoutParams(params); + addView(child); + } + + @Override + public void addView(@NonNull final View child) { + if (child.getTag() != null) super.addView(child); + else frameLayout.addView(child); + } + + @Override + public boolean onInterceptTouchEvent(@NonNull final MotionEvent ev) { + final float x = ev.getX(); + final float y = ev.getY(); + + // another one of my own weird hack thingies to make this app work + if (feedPosts == null) feedPosts = findViewById(R.id.feedPosts); + if (feedPosts != null) { + for (int i = 0; i < feedPosts.getChildCount(); ++i) { + final View viewHolder = feedPosts.getChildAt(i); + final View mediaList = viewHolder.findViewById(R.id.media_list); + if (mediaList instanceof ViewPager) { + final ViewPager viewPager = (ViewPager) mediaList; + + final Rect rect = new Rect(); + viewPager.getGlobalVisibleRect(rect); + + final boolean touchIsInMediaList = rect.contains((int) x, (int) y); + if (touchIsInMediaList) { + final PagerAdapter adapter = viewPager.getAdapter(); + final int count = adapter != null ? adapter.getCount() : 0; + if (count < 1 || viewPager.getCurrentItem() != count - 1) return false; + break; + } + } + } + } + + // thanks to Fede @ https://stackoverflow.com/questions/6920137/android-viewpager-and-horizontalscrollview/7258579#7258579 + if (scroll == null) scroll = findViewById(R.id.highlightsList); + if (scroll != null) { + final boolean touchIsInRecycler = x >= scroll.getLeft() && x < scroll.getRight() + && y >= scroll.getTop() && scroll.getBottom() > y; + + if (touchIsInRecycler) { + final int action = ev.getActionMasked(); + + if (action == MotionEvent.ACTION_CANCEL) return super.onInterceptTouchEvent(ev); + + if (action == MotionEvent.ACTION_DOWN) startX = x; + else if (action == MotionEvent.ACTION_MOVE) { + final int scrollRange = scroll.computeHorizontalScrollRange(); + final int scrollOffset = scroll.computeHorizontalScrollOffset(); + final boolean scrollable = scrollRange > scroll.getWidth(); + final boolean draggingFromRight = startX > x; + + if (scrollOffset < 1) { + if (!scrollable) return super.onInterceptTouchEvent(ev); + else if (!draggingFromRight) return super.onInterceptTouchEvent(ev); + } else if (scrollable && draggingFromRight && scrollRange - scrollOffset == scroll.computeHorizontalScrollExtent()) { + return super.onInterceptTouchEvent(ev); + } + + return false; + } + } + } + return super.onInterceptTouchEvent(ev); + } + + @Override + public void onDrawerSlide(@NonNull final View view, @EdgeGravity final int gravity, final float slideOffset) { + drawerView = view; + final int absHorizGravity = getDrawerViewAbsoluteGravity(GravityCompat.START); + final int childAbsGravity = getDrawerViewAbsoluteGravity(drawerView); + + final Window window = getActivity(getContext()).getWindow(); + final boolean isRtl = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL + || window.getDecorView().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL + || getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL); + + final int drawerViewWidth = drawerView.getWidth(); + + // for (int i = 0; i < frameLayout.getChildCount(); i++) { + // final View child = frameLayout.getChildAt(i); + // + // final boolean isLeftDrawer = isRtl == (childAbsGravity != absHorizGravity); + // float width = isLeftDrawer ? drawerViewWidth : -drawerViewWidth; + // + // child.setX(width * slideOffset); + // } + + final boolean isLeftDrawer = isRtl == (childAbsGravity != absHorizGravity); + float width = isLeftDrawer ? drawerViewWidth : -drawerViewWidth; + + frameLayout.setX(width * (isRtl ? -slideOffset : slideOffset)); + } + + @Override + public void openDrawer(@NonNull final View drawerView, final boolean animate) { + super.openDrawer(drawerView, animate); + post(() -> onDrawerSlide(drawerView, Gravity.NO_GRAVITY, isDrawerOpen(drawerView) ? 1f : 0f)); + } + + @Override + protected void onConfigurationChanged(final Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (drawerView != null) onDrawerSlide(drawerView, Gravity.NO_GRAVITY, isDrawerOpen(drawerView) ? 1f : 0f); + } + + private static Activity getActivity(final Context context) { + if (context != null) { + if (context instanceof Activity) return (Activity) context; + if (context instanceof ContextWrapper) + return getActivity(((ContextWrapper) context).getBaseContext()); + } + return null; + } + + final int getDrawerViewAbsoluteGravity(final int gravity) { + return GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(this)) & GravityCompat.RELATIVE_HORIZONTAL_GRAVITY_MASK; + } + + final int getDrawerViewAbsoluteGravity(@NonNull final View drawerView) { + final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity; + return getDrawerViewAbsoluteGravity(gravity); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/customviews/helpers/GridAutofitLayoutManager.java b/app/src/main/java/awais/instagrabber/customviews/helpers/GridAutofitLayoutManager.java new file mode 100755 index 00000000..d10d96b8 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/helpers/GridAutofitLayoutManager.java @@ -0,0 +1,37 @@ +package awais.instagrabber.customviews.helpers; + +import android.content.Context; + +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import awais.instagrabber.utils.Utils; + +public class GridAutofitLayoutManager extends GridLayoutManager { + private int mColumnWidth; + private boolean mColumnWidthChanged = true; + + public GridAutofitLayoutManager(Context context, int columnWidth) { + super(context, 1); + if (columnWidth <= 0) columnWidth = (int) (48 * Utils.displayMetrics.density); + if (columnWidth > 0 && columnWidth != mColumnWidth) { + mColumnWidth = columnWidth; + mColumnWidthChanged = true; + } + } + + @Override + public void onLayoutChildren(final RecyclerView.Recycler recycler, final RecyclerView.State state) { + final int width = getWidth(); + final int height = getHeight(); + if (mColumnWidthChanged && mColumnWidth > 0 && width > 0 && height > 0) { + final int totalSpace = getOrientation() == VERTICAL ? width - getPaddingRight() - getPaddingLeft() + : height - getPaddingTop() - getPaddingBottom(); + + setSpanCount(Math.max(1, totalSpace / mColumnWidth)); + + mColumnWidthChanged = false; + } + super.onLayoutChildren(recycler, state); + } +} diff --git a/app/src/main/java/awais/instagrabber/customviews/helpers/GridSpacingItemDecoration.java b/app/src/main/java/awais/instagrabber/customviews/helpers/GridSpacingItemDecoration.java new file mode 100755 index 00000000..c0f24d21 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/helpers/GridSpacingItemDecoration.java @@ -0,0 +1,31 @@ +package awais.instagrabber.customviews.helpers; + +import android.graphics.Rect; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration { + private final int spacing; + + public GridSpacingItemDecoration(int spacing) { + this.spacing = spacing; + } + + @Override + public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { + final RecyclerView.LayoutManager manager = parent.getLayoutManager(); + if (manager instanceof GridLayoutManager) { + final int spanCount = ((GridLayoutManager) manager).getSpanCount(); + final int position = parent.getChildAdapterPosition(view); + final int column = position % spanCount; + + outRect.left = column * spacing / spanCount; + outRect.right = spacing - (column + 1) * spacing / spanCount; + if (position < spanCount) outRect.top = spacing; + outRect.bottom = spacing; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/customviews/helpers/RecyclerLazyLoader.java b/app/src/main/java/awais/instagrabber/customviews/helpers/RecyclerLazyLoader.java new file mode 100755 index 00000000..b71eed0b --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/helpers/RecyclerLazyLoader.java @@ -0,0 +1,67 @@ +package awais.instagrabber.customviews.helpers; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import awais.instagrabber.interfaces.LazyLoadListener; + +// thanks to nesquena's EndlessRecyclerViewScrollListener +// https://gist.github.com/nesquena/d09dc68ff07e845cc622 +public final class RecyclerLazyLoader extends RecyclerView.OnScrollListener { + private int currentPage = 0; // The current offset index of data you have loaded + private int previousTotalItemCount = 0; // The total number of items in the dataset after the last load + private boolean loading = true; // True if we are still waiting for the last set of data to load. + private final int visibleThreshold; // The minimum amount of items to have below your current scroll position before loading more. + private final LazyLoadListener lazyLoadListener; + private final RecyclerView.LayoutManager layoutManager; + + public RecyclerLazyLoader(@NonNull final RecyclerView.LayoutManager layoutManager, final LazyLoadListener lazyLoadListener) { + this.layoutManager = layoutManager; + this.lazyLoadListener = lazyLoadListener; + if (layoutManager instanceof GridLayoutManager) { + this.visibleThreshold = 5 * Math.max(3, ((GridLayoutManager) layoutManager).getSpanCount()); + } else if (layoutManager instanceof LinearLayoutManager) { + this.visibleThreshold = ((LinearLayoutManager) layoutManager).getReverseLayout() ? 4 : 8; + } else { + this.visibleThreshold = 5; + } + } + + @Override + public void onScrolled(@NonNull final RecyclerView recyclerView, final int dx, final int dy) { + final int totalItemCount = layoutManager.getItemCount(); + + if (totalItemCount < previousTotalItemCount) { + currentPage = 0; + previousTotalItemCount = totalItemCount; + if (totalItemCount == 0) loading = true; + } + + if (loading && totalItemCount > previousTotalItemCount) { + loading = false; + previousTotalItemCount = totalItemCount; + } + + final int lastVisibleItemPosition; + if (layoutManager instanceof GridLayoutManager) { + final GridLayoutManager layoutManager = (GridLayoutManager) this.layoutManager; + lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition(); + } else { + final LinearLayoutManager layoutManager = (LinearLayoutManager) this.layoutManager; + lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition(); + } + + if (!loading && lastVisibleItemPosition + visibleThreshold > totalItemCount) { + if (lazyLoadListener != null) lazyLoadListener.onLoadMore(++currentPage, totalItemCount); + loading = true; + } + } + + public void resetState() { + this.currentPage = 0; + this.previousTotalItemCount = 0; + this.loading = true; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/customviews/helpers/SwipeGestureListener.java b/app/src/main/java/awais/instagrabber/customviews/helpers/SwipeGestureListener.java new file mode 100755 index 00000000..fcd3f809 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/helpers/SwipeGestureListener.java @@ -0,0 +1,34 @@ +package awais.instagrabber.customviews.helpers; + +import android.util.Log; +import android.view.GestureDetector; +import android.view.MotionEvent; + +import awais.instagrabber.interfaces.SwipeEvent; + +public final class SwipeGestureListener extends GestureDetector.SimpleOnGestureListener { + public static final int SWIPE_THRESHOLD = 200; + public static final int SWIPE_VELOCITY_THRESHOLD = 200; + private final SwipeEvent swipeEvent; + + public SwipeGestureListener(final SwipeEvent swipeEvent) { + this.swipeEvent = swipeEvent; + } + + @Override + public boolean onFling(final MotionEvent e1, final MotionEvent e2, final float velocityX, final float velocityY) { + try { + final float diffY = e2.getY() - e1.getY(); + final float diffX = e2.getX() - e1.getX(); + final float diffXAbs = Math.abs(diffX); + if (diffXAbs > Math.abs(diffY) && diffXAbs > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) { + if (diffX > 0) swipeEvent.onSwipe(true); + else swipeEvent.onSwipe(false); + return true; + } + } catch (final Exception e) { + Log.e("AWAISKING_APP", "", e); + } + return false; + } +} diff --git a/app/src/main/java/awais/instagrabber/customviews/helpers/VideoAwareRecyclerScroller.java b/app/src/main/java/awais/instagrabber/customviews/helpers/VideoAwareRecyclerScroller.java new file mode 100755 index 00000000..1deff1ad --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/helpers/VideoAwareRecyclerScroller.java @@ -0,0 +1,282 @@ +package awais.instagrabber.customviews.helpers; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.graphics.Rect; +import android.net.Uri; +import android.view.View; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.source.ProgressiveMediaSource; +import com.google.android.exoplayer2.ui.PlayerView; +import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; + +import java.util.List; + +import awais.instagrabber.R; +import awais.instagrabber.activities.CommentsViewer; +import awais.instagrabber.adapters.FeedAdapter; +import awais.instagrabber.models.FeedModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; + +import static awais.instagrabber.utils.Utils.settingsHelper; + +// wasted around 3 hours to get this working, made from scrach, forgot to take a shower so i'm gonna go take a shower (time: May 11, 2020 @ 8:09:30 PM) +public class VideoAwareRecyclerScroller extends RecyclerView.OnScrollListener { + private static final Object LOCK = new Object(); + private LinearLayoutManager layoutManager; + private View firstItemView, lastItemView; + private int videoPosShown = -1, lastVideoPos = -1, lastChangedVideoPos, lastStoppedVideoPos, lastPlayedVideoPos; + private boolean videoAttached = false; + private final List feedModels; + //////////////////////////////////////////////////// + private SimpleExoPlayer player; + private ImageView btnMute; + private final Context context; + private final View.OnClickListener commentClickListener = new View.OnClickListener() { + @Override + public void onClick(@NonNull final View v) { + final Object tag = v.getTag(); + if (tag instanceof FeedModel && context instanceof Activity) { + if (player != null) player.setPlayWhenReady(false); + ((Activity) context).startActivityForResult(new Intent(context, CommentsViewer.class) + .putExtra(Constants.EXTRAS_SHORTCODE, ((FeedModel) tag).getShortCode()), 6969); + } + } + }; + private final View.OnClickListener muteClickListener = v -> { + if (player == null) return; + final float intVol = player.getVolume() == 0f ? 1f : 0f; + player.setVolume(intVol); + if (btnMute != null) btnMute.setImageResource(intVol == 0f ? R.drawable.vol : R.drawable.mute); + Utils.sessionVolumeFull = intVol == 1f; + }; + private final VideoChangeCallback videoChangeCallback; + // private final ScrollerVideoCallback videoCallback; + // private View lastVideoHolder; + // private int videoState = -1; + + public VideoAwareRecyclerScroller(final Context context, final List feedModels, + final VideoChangeCallback videoChangeCallback) { + this.context = context; + this.feedModels = feedModels; + this.videoChangeCallback = videoChangeCallback; + } + + @Override + public void onScrolled(@NonNull final RecyclerView recyclerView, final int dx, final int dy) { + if (layoutManager == null) { + final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); + if (layoutManager instanceof LinearLayoutManager) this.layoutManager = (LinearLayoutManager) layoutManager; + } + + if (feedModels.size() > 0 && layoutManager != null) { + int firstVisibleItemPos = layoutManager.findFirstCompletelyVisibleItemPosition(); + int lastVisibleItemPos = layoutManager.findLastCompletelyVisibleItemPosition(); + + if (firstVisibleItemPos == -1 && lastVisibleItemPos == -1) { + firstVisibleItemPos = layoutManager.findFirstVisibleItemPosition(); + lastVisibleItemPos = layoutManager.findLastVisibleItemPosition(); + } + + boolean processFirstItem = false, processLastItem = false; + View currView; + if (firstVisibleItemPos != -1) { + currView = layoutManager.findViewByPosition(firstVisibleItemPos); + if (currView != null && currView.getId() == R.id.videoHolder) { + firstItemView = currView; + processFirstItem = true; + } + } + if (lastVisibleItemPos != -1) { + currView = layoutManager.findViewByPosition(lastVisibleItemPos); + if (currView != null && currView.getId() == R.id.videoHolder) { + lastItemView = currView; + processLastItem = true; + } + } + + final Rect visibleItemRect = new Rect(); + + int firstVisibleItemHeight = 0, lastVisibleItemHeight = 0; + + final boolean isFirstItemVideoHolder = firstItemView != null && firstItemView.getId() == R.id.videoHolder; + if (isFirstItemVideoHolder) { + firstItemView.getGlobalVisibleRect(visibleItemRect); + firstVisibleItemHeight = visibleItemRect.height(); + } + final boolean isLastItemVideoHolder = lastItemView != null && lastItemView.getId() == R.id.videoHolder; + if (isLastItemVideoHolder) { + lastItemView.getGlobalVisibleRect(visibleItemRect); + lastVisibleItemHeight = visibleItemRect.height(); + } + + if (processFirstItem && firstVisibleItemHeight > lastVisibleItemHeight) videoPosShown = firstVisibleItemPos; + else if (processLastItem && lastVisibleItemHeight != 0) videoPosShown = lastVisibleItemPos; + + if (firstItemView != lastItemView) { + final int mox = lastVisibleItemHeight - firstVisibleItemHeight; + if (processLastItem && lastVisibleItemHeight > firstVisibleItemHeight) videoPosShown = lastVisibleItemPos; + if ((processFirstItem || processLastItem) && mox >= 0) videoPosShown = lastVisibleItemPos; + } + + if (lastChangedVideoPos != -1 && lastVideoPos != -1) { + currView = layoutManager.findViewByPosition(lastChangedVideoPos); + if (currView != null && currView.getId() == R.id.videoHolder && + lastStoppedVideoPos != lastChangedVideoPos && lastPlayedVideoPos != lastChangedVideoPos) { + lastStoppedVideoPos = lastChangedVideoPos; + stopVideo(lastChangedVideoPos, recyclerView, currView); + } + + currView = layoutManager.findViewByPosition(lastVideoPos); + if (currView != null && currView.getId() == R.id.videoHolder) { + final Rect rect = new Rect(); + currView.getGlobalVisibleRect(rect); + + final int holderTop = currView.getTop(); + final int holderHeight = currView.getBottom() - holderTop; + final int halfHeight = holderHeight / 2; + //halfHeight -= halfHeight / 5; + + if (rect.height() < halfHeight) { + if (lastStoppedVideoPos != lastVideoPos) { + lastStoppedVideoPos = lastVideoPos; + stopVideo(lastVideoPos, recyclerView, currView); + } + } else if (lastPlayedVideoPos != lastVideoPos) { + lastPlayedVideoPos = lastVideoPos; + playVideo(lastVideoPos, recyclerView, currView); + } + } + + if (lastChangedVideoPos != lastVideoPos) lastChangedVideoPos = lastVideoPos; + } + + if (lastVideoPos != -1 && lastVideoPos != videoPosShown) { + if (videoAttached) { + //if ((currView = layoutManager.findViewByPosition(lastVideoPos)) != null && currView.getId() == R.id.videoHolder) + releaseVideo(lastVideoPos, recyclerView, null); + videoAttached = false; + } + } + if (videoPosShown != -1) { + lastVideoPos = videoPosShown; + if (!videoAttached) { + if ((currView = layoutManager.findViewByPosition(videoPosShown)) != null && currView.getId() == R.id.videoHolder) + attachVideo(videoPosShown, recyclerView, currView); + videoAttached = true; + } + } + } + } + + private synchronized void attachVideo(final int itemPos, final RecyclerView recyclerView, final View itemView) { + synchronized (LOCK) { + if (recyclerView != null) { + final RecyclerView.Adapter adapter = recyclerView.getAdapter(); + if (adapter instanceof FeedAdapter) { + final SimpleExoPlayer pagerPlayer = ((FeedAdapter) adapter).pagerPlayer; + if (pagerPlayer != null) pagerPlayer.setPlayWhenReady(false); + } + } + + if (player != null) { + player.stop(true); + player.release(); + player = null; + } + + player = new SimpleExoPlayer.Builder(context).build(); + + if (itemView != null) { + final Object tag = itemView.getTag(); + + final View btnComments = itemView.findViewById(R.id.btnComments); + if (btnComments != null && tag instanceof FeedModel) { + final FeedModel feedModel = (FeedModel) tag; + + if (feedModel.getCommentsCount() <= 0) btnComments.setEnabled(false); + else { + btnComments.setTag(feedModel); + btnComments.setEnabled(true); + btnComments.setOnClickListener(commentClickListener); + } + } + + final PlayerView playerView = itemView.findViewById(R.id.playerView); + if (playerView == null) return; + playerView.setPlayer(player); + + if (player != null) { + btnMute = itemView.findViewById(R.id.btnMute); + + float vol = settingsHelper.getBoolean(Constants.MUTED_VIDEOS) ? 0f : 1f; + if (vol == 0f && Utils.sessionVolumeFull) vol = 1f; + player.setVolume(vol); + + if (btnMute != null) { + btnMute.setVisibility(View.VISIBLE); + btnMute.setImageResource(vol == 0f ? R.drawable.vol : R.drawable.mute); + btnMute.setOnClickListener(muteClickListener); + } + + player.setPlayWhenReady(settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS)); + + final ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(new DefaultDataSourceFactory(context, "instagram")) + .createMediaSource(Uri.parse(feedModels.get(itemPos).getDisplayUrl())); + + player.setRepeatMode(Player.REPEAT_MODE_ALL); + player.prepare(mediaSource); + player.setVolume(vol); + + playerView.setOnClickListener(muteClickListener); + } + } + + if (videoChangeCallback != null) videoChangeCallback.playerChanged(itemPos, player); + } + } + + private void releaseVideo(final int itemPos, final RecyclerView recyclerView, final View itemView) { +// Log.d("AWAISKING_APP", "release: " + itemPos); +// if (player != null) { +// player.stop(true); +// player.release(); +// } +// player = null; + } + + private void playVideo(final int itemPos, final RecyclerView recyclerView, final View itemView) { +// if (player != null) { +// final int playbackState = player.getPlaybackState(); +// if (!player.isPlaying() +// || playbackState == Player.STATE_READY || playbackState == Player.STATE_ENDED +// ) { +// player.setPlayWhenReady(true); +// } +// } +// if (player != null) { +// player.setPlayWhenReady(true); +// player.getPlaybackState(); +// } + } + + private void stopVideo(final int itemPos, final RecyclerView recyclerView, final View itemView) { + if (player != null) { + player.setPlayWhenReady(false); + player.getPlaybackState(); + } + } + + public interface VideoChangeCallback { + void playerChanged(final int itemPos, final SimpleExoPlayer player); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/SoundParser.java b/app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/SoundParser.java new file mode 100755 index 00000000..6fb309d5 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/SoundParser.java @@ -0,0 +1,252 @@ +package awais.instagrabber.customviews.masoudss_waveform; + +import android.media.MediaCodec; +import android.media.MediaExtractor; +import android.media.MediaFormat; +import android.nfc.FormatException; +import android.os.Build; + +import androidx.annotation.NonNull; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.ShortBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +final class SoundParser { + private ProgressListener progressListener; + int[] frameGains; + ////////////////// + private static String[] supportedExtensions = {"mp3", "wav", "3gpp", "3gp", "amr", "aac", "m4a", "ogg"}; + private static ArrayList additionalExtensions = new ArrayList<>(); + + static void addCustomExtension(final String extension) { + additionalExtensions.add(extension); + } + + static void removeCustomExtension(final String extension) { + additionalExtensions.remove(extension); + } + + static void addCustomExtensions(final List extensions) { + additionalExtensions.addAll(extensions); + } + + static void removeCustomExtensions(final List extensions) { + additionalExtensions.removeAll(extensions); + } + + private static boolean isFilenameSupported(final String filename) { + for (final String supportedExtension : supportedExtensions) + if (filename.endsWith('.' + supportedExtension)) return true; + for (final String additionalExtension : additionalExtensions) + if (filename.endsWith('.' + additionalExtension)) return true; + return false; + } + + @NonNull + public static SoundParser create(final String fileName, final boolean ignoreExtension) throws IOException, FormatException { + if (!ignoreExtension && !isFilenameSupported(fileName)) + throw new FormatException("Not supported file extension."); + + final File f = new File(fileName); + if (!f.exists()) throw new FileNotFoundException(fileName); + + final SoundParser soundFile = new SoundParser(); + soundFile.readFile(f); + + return soundFile; + } + + public void setProgressListener(final ProgressListener progressListener) { + this.progressListener = progressListener; + } + + @SuppressWarnings("deprecation") + private void readFile(@NonNull final File inputFile) throws IOException, FormatException { + final MediaExtractor extractor = new MediaExtractor(); + MediaFormat format = null; + + final int fileSizeBytes = (int) inputFile.length(); + extractor.setDataSource(inputFile.getPath()); + + final int numTracks = extractor.getTrackCount(); + + int i = 0; + while (i < numTracks) { + format = extractor.getTrackFormat(i); + if (Objects.requireNonNull(format.getString(MediaFormat.KEY_MIME)).startsWith("audio/")) { + extractor.selectTrack(i); + break; + } + i++; + } + + if (i == numTracks) throw new FormatException("No audio track found in " + inputFile); + assert format != null; + + final int channels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT); + final int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE); + + final int expectedNumSamples = (int) (format.getLong(MediaFormat.KEY_DURATION) / 1000000f * sampleRate + 0.5f); + + final MediaCodec codec = MediaCodec.createDecoderByType(Objects.requireNonNull(format.getString(MediaFormat.KEY_MIME))); + codec.configure(format, null, null, 0); + codec.start(); + + final MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); + final ByteBuffer[] inputBuffers = codec.getInputBuffers(); + + boolean firstSampleData = true, doneReading = false; + long presentationTime; + int sampleSize, decodedSamplesSize = 0, totSizeRead = 0; + byte[] decodedSamples = null; + ByteBuffer mDecodedBytes = ByteBuffer.allocate(1 << 20); + ByteBuffer[] outputBuffers = codec.getOutputBuffers(); + + while (true) { + final int inputBufferIndex = codec.dequeueInputBuffer(100); + + if (!doneReading && inputBufferIndex >= 0) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) + sampleSize = extractor.readSampleData(Objects.requireNonNull(codec.getInputBuffer(inputBufferIndex)), 0); + else + sampleSize = extractor.readSampleData(inputBuffers[inputBufferIndex], 0); + + if (firstSampleData && sampleSize == 2 && "audio/mp4a-latm".equals(format.getString(MediaFormat.KEY_MIME))) { + extractor.advance(); + totSizeRead += sampleSize; + } else if (sampleSize < 0) { + codec.queueInputBuffer(inputBufferIndex, 0, 0, -1, MediaCodec.BUFFER_FLAG_END_OF_STREAM); + doneReading = true; + } else { + presentationTime = extractor.getSampleTime(); + codec.queueInputBuffer(inputBufferIndex, 0, sampleSize, presentationTime, 0); + extractor.advance(); + totSizeRead += sampleSize; + + if (progressListener != null && !progressListener.reportProgress((double) totSizeRead / fileSizeBytes)) { + // We are asked to stop reading the file. Returning immediately. + // The SoundFile object is invalid and should NOT be used afterward! + extractor.release(); + codec.stop(); + codec.release(); + return; + } + } + + firstSampleData = false; + } + + // Get decoded stream from the decoder output buffers. + final int outputBufferIndex = codec.dequeueOutputBuffer(info, 100); + if (outputBufferIndex >= 0 && info.size > 0) { + if (decodedSamplesSize < info.size) { + decodedSamplesSize = info.size; + decodedSamples = new byte[decodedSamplesSize]; + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + final ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferIndex); + assert outputBuffer != null; + outputBuffer.get(decodedSamples, 0, info.size); + outputBuffer.clear(); + } else { + outputBuffers[outputBufferIndex].get(decodedSamples, 0, info.size); + outputBuffers[outputBufferIndex].clear(); + } + + // Check if buffer is big enough. Resize it if it's too small. + if (mDecodedBytes.remaining() < info.size) { + // Getting a rough estimate of the total size, allocate 20% more, and + // make sure to allocate at least 5MB more than the initial size. + final int position = mDecodedBytes.position(); + + int newSize = (int) (position * (1.0 * fileSizeBytes / totSizeRead) * 1.2); + final int infoSize = info.size + 5 * (1 << 20); + if (newSize - position < infoSize) + newSize = position + infoSize; + + ByteBuffer newDecodedBytes = null; + + // Try to allocate memory. If we are OOM, try to run the garbage collector. + int retry = 10; + while (retry > 0) { + try { + newDecodedBytes = ByteBuffer.allocate(newSize); + break; + } catch (final OutOfMemoryError e) { + retry--; + } + } + if (retry == 0) break; + mDecodedBytes.rewind(); + assert newDecodedBytes != null; + newDecodedBytes.put(mDecodedBytes); + mDecodedBytes = newDecodedBytes; + mDecodedBytes.position(position); + } + + mDecodedBytes.put(decodedSamples, 0, info.size); + codec.releaseOutputBuffer(outputBufferIndex, false); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) + outputBuffers = codec.getOutputBuffers(); + } + + if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0 || mDecodedBytes.position() / (2 * channels) >= expectedNumSamples) + break; + } + + final int numSamples = mDecodedBytes.position() / (channels * 2); // One sample = 2 bytes. + mDecodedBytes.rewind(); + mDecodedBytes.order(ByteOrder.LITTLE_ENDIAN); + final ShortBuffer mDecodedSamples = mDecodedBytes.asShortBuffer(); + // final int avgBitrateKbps = (int) (fileSizeBytes * 8F * ((float) sampleRate / numSamples) / 1000F); + + extractor.release(); + codec.stop(); + codec.release(); + + final int samplesPerFrame = 1024; + int numFrames = numSamples / samplesPerFrame; + if (numSamples % samplesPerFrame != 0) numFrames++; + frameGains = new int[numFrames]; + // final int[] mFrameLens = new int[numFrames]; + // final int[] mFrameOffsets = new int[numFrames]; + // final int frameLens = (int) (1000F * avgBitrateKbps / 8F * ((float) samplesPerFrame / sampleRate)); + int j, gain, value; + + i = 0; + while (i < numFrames) { + gain = -1; + j = 0; + + while (j < samplesPerFrame) { + value = 0; + for (int k = 0; k < channels; ++k) + if (mDecodedSamples.remaining() > 0) + value += Math.abs(mDecodedSamples.get()); + value /= channels; + if (gain < value) gain = value; + j++; + } + + frameGains[i] = (int) Math.sqrt(gain); + // mFrameLens[i] = frameLens; + // mFrameOffsets[i] = (int) ((float) i * (1000F * avgBitrateKbps / 8F) * ((float) samplesPerFrame / sampleRate)); + i++; + } + + mDecodedSamples.rewind(); + } + + private interface ProgressListener { + boolean reportProgress(final double fractionComplete); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/WaveFormProgressChangeListener.java b/app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/WaveFormProgressChangeListener.java new file mode 100755 index 00000000..326bc102 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/WaveFormProgressChangeListener.java @@ -0,0 +1,5 @@ +package awais.instagrabber.customviews.masoudss_waveform; + +public interface WaveFormProgressChangeListener { + void onProgressChanged(final WaveformSeekBar waveformSeekBar, final int progress, final boolean fromUser); +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/WaveGravity.java b/app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/WaveGravity.java new file mode 100755 index 00000000..5ac68de0 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/WaveGravity.java @@ -0,0 +1,7 @@ +package awais.instagrabber.customviews.masoudss_waveform; + +public enum WaveGravity { + TOP, + CENTER, + BOTTOM, +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/WaveformSeekBar.java b/app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/WaveformSeekBar.java new file mode 100755 index 00000000..6132a6e4 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/WaveformSeekBar.java @@ -0,0 +1,225 @@ +package awais.instagrabber.customviews.masoudss_waveform; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Shader; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; + +import awais.instagrabber.R; +import awais.instagrabber.utils.Utils; + +public final class WaveformSeekBar extends View { + private final int mScaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); + private final Paint mWavePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final RectF mWaveRect = new RectF(); + private final Canvas mProgressCanvas = new Canvas(); + private final WaveGravity waveGravity = WaveGravity.BOTTOM; + private final int waveBackgroundColor; + private final int waveProgressColor; + private final float waveWidth = Utils.convertDpToPx(3); + private final float waveMinHeight = Utils.convertDpToPx(4); + private final float waveCornerRadius = Utils.convertDpToPx(2); + private final float waveGap = Utils.convertDpToPx(1); + private int mCanvasWidth = 0; + private int mCanvasHeight = 0; + private float mTouchDownX = 0F; + private int[] sample; + private int progress = 0; + private WaveFormProgressChangeListener progressChangeListener; + + public WaveformSeekBar(final Context context) { + this(context, null); + } + + public WaveformSeekBar(final Context context, @Nullable final AttributeSet attrs) { + this(context, attrs, 0); + } + + public WaveformSeekBar(final Context context, @Nullable final AttributeSet attrs, final int defStyleAttr) { + super(context, attrs, defStyleAttr); + this.waveBackgroundColor = ContextCompat.getColor(context, R.color.text_color_light); + this.waveProgressColor = ContextCompat.getColor(context, R.color.text_color_dark); + } + + private int getSampleMax() { + int max = -1; + if (sample != null) for (final int i : sample) if (i >= max) max = i; + return max; + } + + @SuppressLint("DrawAllocation") + @Override + protected void onDraw(final Canvas canvas) { + super.onDraw(canvas); + if (sample != null && sample.length != 0) { + final int availableWidth = getAvailableWidth(); + final int availableHeight = getAvailableHeight(); + + final float step = availableWidth / (waveGap + waveWidth) / sample.length; + + float i = 0F; + float lastWaveRight = (float) getPaddingLeft(); + + final int sampleMax = getSampleMax(); + while (i < sample.length) { + float waveHeight = availableHeight * ((float) sample[(int) i] / sampleMax); + + if (waveHeight < waveMinHeight) + waveHeight = waveMinHeight; + + final float top; + if (waveGravity == WaveGravity.TOP) { + top = (float) getPaddingTop(); + } else if (waveGravity == WaveGravity.CENTER) { + top = (float) getPaddingTop() + availableHeight / 2F - waveHeight / 2F; + } else if (waveGravity == WaveGravity.BOTTOM) { + top = mCanvasHeight - (float) getPaddingBottom() - waveHeight; + } else { + top = 0; + } + + mWaveRect.set(lastWaveRight, top, lastWaveRight + waveWidth, top + waveHeight); + + if (mWaveRect.contains(availableWidth * progress / 100F, mWaveRect.centerY())) { + int bitHeight = (int) mWaveRect.height(); + if (bitHeight <= 0) bitHeight = (int) waveWidth; + + final Bitmap bitmap = Bitmap.createBitmap(availableWidth, bitHeight, Bitmap.Config.ARGB_8888); + mProgressCanvas.setBitmap(bitmap); + + float fillWidth = availableWidth * progress / 100F; + + mWavePaint.setColor(waveProgressColor); + mProgressCanvas.drawRect(0F, 0F, fillWidth, mWaveRect.bottom, mWavePaint); + + mWavePaint.setColor(waveBackgroundColor); + mProgressCanvas.drawRect(fillWidth, 0F, (float) availableWidth, mWaveRect.bottom, mWavePaint); + + mWavePaint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)); + } else { + mWavePaint.setColor(mWaveRect.right <= availableWidth * progress / 100F ? waveProgressColor : waveBackgroundColor); + mWavePaint.setShader(null); + } + + canvas.drawRoundRect(mWaveRect, waveCornerRadius, waveCornerRadius, mWavePaint); + + lastWaveRight = mWaveRect.right + waveGap; + + if (lastWaveRight + waveWidth > availableWidth + getPaddingLeft()) + break; + + i += 1 / step; + } + } + } + + @Override + public boolean onTouchEvent(final MotionEvent event) { + if (!isEnabled()) return false; + + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + if (isParentScrolling()) mTouchDownX = event.getX(); + else updateProgress(event); + break; + + case MotionEvent.ACTION_MOVE: + updateProgress(event); + break; + + case MotionEvent.ACTION_UP: + if (Math.abs(event.getX() - mTouchDownX) > mScaledTouchSlop) + updateProgress(event); + + performClick(); + break; + } + + return true; + } + + @Override + protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + mCanvasWidth = w; + mCanvasHeight = h; + } + + @Override + public boolean performClick() { + super.performClick(); + return true; + } + + private boolean isParentScrolling() { + View parent = (View) getParent(); + final View root = getRootView(); + + while (true) { + if (parent.canScrollHorizontally(1) || parent.canScrollHorizontally(-1) || + parent.canScrollVertically(1) || parent.canScrollVertically(-1)) + return true; + + if (parent == root) return false; + + parent = (View) parent.getParent(); + } + } + + private void updateProgress(@NonNull final MotionEvent event) { + progress = (int) (100 * event.getX() / getAvailableWidth()); + invalidate(); + + if (progressChangeListener != null) + progressChangeListener.onProgressChanged(this, Math.min(Math.max(0, progress), 100), true); + } + + private int getAvailableWidth() { + return mCanvasWidth - getPaddingLeft() - getPaddingRight(); + } + + private int getAvailableHeight() { + return mCanvasHeight - getPaddingTop() - getPaddingBottom(); + } + + // public void setSampleFrom(final String path, final boolean ignoreExtension) { // was false + // try { + // final SoundParser soundFile = SoundParser.create(path, ignoreExtension); + // sample = soundFile.frameGains; + // } catch (final Exception e) { + // sample = null; + // } + // } + // + // public void setSampleFrom(@NonNull final File file, final boolean ignoreExtension) { // was false + // setSampleFrom(file.getAbsolutePath(), ignoreExtension); + // } + + public void setProgress(final int progress) { + this.progress = progress; + invalidate(); + } + + public void setProgressChangeListener(final WaveFormProgressChangeListener progressChangeListener) { + this.progressChangeListener = progressChangeListener; + } + + public void setSample(final int[] sample) { + if (sample != this.sample) { + this.sample = sample; + invalidate(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/dialogs/AboutDialog.java b/app/src/main/java/awais/instagrabber/dialogs/AboutDialog.java new file mode 100755 index 00000000..f727b885 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/dialogs/AboutDialog.java @@ -0,0 +1,98 @@ +package awais.instagrabber.dialogs; + +import android.app.Dialog; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.text.SpannableStringBuilder; +import android.text.method.LinkMovementMethod; +import android.text.style.RelativeSizeSpan; +import android.text.style.URLSpan; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.LinearLayoutCompat; + +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; + +import awais.instagrabber.R; +import awais.instagrabber.utils.Utils; + +public final class AboutDialog extends BottomSheetDialogFragment { + @NonNull + @Override + public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) { + final Dialog dialog = super.onCreateDialog(savedInstanceState); + final View contentView = View.inflate(getContext(), R.layout.dialog_main_about, null); + + final LinearLayoutCompat infoContainer = contentView.findViewById(R.id.infoContainer); + + final View btnTelegram = infoContainer.getChildAt(1); + final View btnProject = infoContainer.getChildAt(2); + final View.OnClickListener onClickListener = v -> { + final Intent intent = new Intent(Intent.ACTION_VIEW); + if (v == btnTelegram) { + intent.setData(Uri.parse("https://t.me/grabber_app")); + if (!Utils.isEmpty(Utils.telegramPackage)) + intent.setPackage(Utils.telegramPackage); + } else + intent.setData(Uri.parse("https://gitlab.com/AwaisKing/instagrabber/")); + startActivity(intent); + }; + btnProject.setOnClickListener(onClickListener); + btnTelegram.setOnClickListener(onClickListener); + + final String description = getString(R.string.description); + if (!Utils.isEmpty(description)) { + final SpannableStringBuilder descriptionText = new SpannableStringBuilder(description, 0, description.length()); + + int lastIndex = descriptionText.length() / 2; + for (int i = 0; i < descriptionText.length(); ++i) { + char c = descriptionText.charAt(i); + + if (c == '[') { + final int smallTextStart = i; + descriptionText.delete(i, i + 1); + + do { + c = descriptionText.charAt(i); + if (c == ']') { + descriptionText.delete(i, i + 1); + descriptionText.setSpan(new RelativeSizeSpan(0.5f), smallTextStart, i, 0); + } + ++i; + } while (c != ']' || i == descriptionText.length() - 1); + } else if (c == '{') { + final int smallerTextStart = i; + descriptionText.delete(i, i + 1); + i = smallerTextStart; + + do { + c = descriptionText.charAt(i); + if (c == '}') { + descriptionText.delete(i, i + 1); + descriptionText.setSpan(new RelativeSizeSpan(0.35f), smallerTextStart, i, 0); + } + ++i; + lastIndex = i; + } while (c != '}' || i == descriptionText.length() - 1); + } + } + + lastIndex = Utils.indexOfChar(descriptionText, '@', lastIndex); + descriptionText.setSpan(new URLSpan("https://t.me/awais404"), lastIndex, lastIndex + 9, 0); + + lastIndex = Utils.indexOfChar(descriptionText, ':', lastIndex + 9) + 2; + descriptionText.setSpan(new URLSpan("mailto:chapter50000@hotmail.com"), lastIndex, lastIndex + 24, 0); + + final TextView textView = (TextView) infoContainer.getChildAt(0); + textView.setMovementMethod(new LinkMovementMethod()); + textView.setText(descriptionText, TextView.BufferType.SPANNABLE); + } + + dialog.setContentView(contentView); + return dialog; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/dialogs/ProfileSettingsDialog.java b/app/src/main/java/awais/instagrabber/dialogs/ProfileSettingsDialog.java new file mode 100755 index 00000000..909227c3 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/dialogs/ProfileSettingsDialog.java @@ -0,0 +1,62 @@ +package awais.instagrabber.dialogs; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.View; +import android.widget.AdapterView; +import android.widget.Spinner; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; + +import awais.instagrabber.R; + +import static awais.instagrabber.utils.Constants.PROFILE_FETCH_MODE; +import static awais.instagrabber.utils.Utils.settingsHelper; + +public final class ProfileSettingsDialog extends BottomSheetDialogFragment implements AdapterView.OnItemSelectedListener { + private int fetchIndex; + private Activity activity; + private Spinner spProfileFetchMode; + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + final Dialog dialog = super.onCreateDialog(savedInstanceState); + + final Context context = getContext(); + activity = context instanceof Activity ? (Activity) context : getActivity(); + + final View contentView = View.inflate(activity, R.layout.dialog_profile_settings, null); + + spProfileFetchMode = contentView.findViewById(R.id.spProfileFetchMode); + + fetchIndex = Math.min(2, Math.max(0, settingsHelper.getInteger(PROFILE_FETCH_MODE))); + spProfileFetchMode.setSelection(fetchIndex); + spProfileFetchMode.setOnItemSelectedListener(this); + + dialog.setContentView(contentView); + + return dialog; + } + + @Override + public void onDismiss(@NonNull final DialogInterface dialog) { + super.onDismiss(dialog); + if (activity != null && (spProfileFetchMode == null || fetchIndex != spProfileFetchMode.getSelectedItemPosition())) + activity.recreate(); + } + + @Override + public void onItemSelected(final AdapterView parent, final View view, final int position, final long id) { + settingsHelper.putInteger(PROFILE_FETCH_MODE, position); + } + + @Override + public void onNothingSelected(final AdapterView parent) { } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/dialogs/QuickAccessDialog.java b/app/src/main/java/awais/instagrabber/dialogs/QuickAccessDialog.java new file mode 100755 index 00000000..ddae5a62 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/dialogs/QuickAccessDialog.java @@ -0,0 +1,169 @@ +package awais.instagrabber.dialogs; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.view.View; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; + +import java.util.ArrayList; + +import awais.instagrabber.R; +import awais.instagrabber.activities.Main; +import awais.instagrabber.adapters.SimpleAdapter; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.DataBox; +import awais.instagrabber.utils.Utils; + +import static awais.instagrabber.utils.Utils.settingsHelper; + +public final class QuickAccessDialog extends BottomSheetDialogFragment implements DialogInterface.OnShowListener, + View.OnClickListener, View.OnLongClickListener { + private boolean cookieChanged, isQuery; + private Activity activity; + private String userQuery; + private View btnFavorite, btnImportExport; + private SimpleAdapter favoritesAdapter; + + public QuickAccessDialog setQuery(final String userQuery) { + this.userQuery = userQuery; + return this; + } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + final Dialog dialog = super.onCreateDialog(savedInstanceState); + + dialog.setOnShowListener(this); + + final Context context = getContext(); + activity = context instanceof Activity ? (Activity) context : getActivity(); + + final View contentView = View.inflate(activity, R.layout.dialog_quick_access, null); + + btnFavorite = contentView.findViewById(R.id.btnFavorite); + btnImportExport = contentView.findViewById(R.id.importExport); + + isQuery = !Utils.isEmpty(userQuery); + btnFavorite.setVisibility(isQuery ? View.VISIBLE : View.GONE); + Utils.setTooltipText(btnImportExport, R.string.import_export); + + favoritesAdapter = new SimpleAdapter<>(activity, Utils.dataBox.getAllFavorites(), this, this); + + btnFavorite.setOnClickListener(this); + btnImportExport.setOnClickListener(this); + + final RecyclerView rvFavorites = contentView.findViewById(R.id.rvFavorites); + final RecyclerView rvQuickAccess = contentView.findViewById(R.id.rvQuickAccess); + + final DividerItemDecoration itemDecoration = new DividerItemDecoration(activity, DividerItemDecoration.VERTICAL); + rvFavorites.addItemDecoration(itemDecoration); + rvFavorites.setAdapter(favoritesAdapter); + + final String cookieStr = settingsHelper.getString(Constants.COOKIE); + if (!Utils.isEmpty(cookieStr) + || Utils.dataBox.getCookieCount() > 0 // fallback for export / import + ) { + rvQuickAccess.addItemDecoration(itemDecoration); + final ArrayList allCookies = Utils.dataBox.getAllCookies(); + if (!Utils.isEmpty(cookieStr) && allCookies != null) { + for (final DataBox.CookieModel cookie : allCookies) { + if (cookieStr.equals(cookie.getCookie())) { + cookie.setSelected(true); + break; + } + } + } + rvQuickAccess.setAdapter(new SimpleAdapter<>(activity, allCookies, this, this)); + } else { + ((View) rvQuickAccess.getParent()).setVisibility(View.GONE); + } + + dialog.setContentView(contentView); + return dialog; + } + + @Override + public void onClick(@NonNull final View v) { + final Object tag = v.getTag(); + if (v == btnFavorite) { + if (isQuery) { + Utils.dataBox.addFavorite(new DataBox.FavoriteModel(userQuery, System.currentTimeMillis())); + favoritesAdapter.setItems(Utils.dataBox.getAllFavorites()); + } + } else if (v == btnImportExport) { + if (ContextCompat.checkSelfPermission(activity, Utils.PERMS[0]) == PackageManager.PERMISSION_DENIED) + requestPermissions(Utils.PERMS, 6007); + else Utils.showImportExportDialog(v.getContext()); + + } else if (tag instanceof DataBox.FavoriteModel) { + if (Main.scanHack != null) { + Main.scanHack.onResult(((DataBox.FavoriteModel) tag).getQuery()); + dismiss(); + } + + } else if (tag instanceof DataBox.CookieModel) { + final DataBox.CookieModel cookieModel = (DataBox.CookieModel) tag; + if (!cookieModel.isSelected()) { + settingsHelper.putString(Constants.COOKIE, cookieModel.getCookie()); + Utils.setupCookies(cookieModel.getCookie()); + cookieChanged = true; + } + dismiss(); + } + } + + @Override + public boolean onLongClick(@NonNull final View v) { + final Object tag = v.getTag(); + + if (tag instanceof DataBox.FavoriteModel) { + final DataBox.FavoriteModel favoriteModel = (DataBox.FavoriteModel) tag; + + new AlertDialog.Builder(activity).setPositiveButton(R.string.yes, (d, which) -> Utils.dataBox.delFavorite(favoriteModel)) + .setNegativeButton(R.string.no, null).setMessage(getString(R.string.quick_access_confirm_delete, + favoriteModel.getQuery())).show(); + + } else if (tag instanceof DataBox.CookieModel) { + final DataBox.CookieModel cookieModel = (DataBox.CookieModel) tag; + + if (cookieModel.isSelected()) + Toast.makeText(v.getContext(), R.string.quick_access_cannot_delete_curr, Toast.LENGTH_SHORT).show(); + else + new AlertDialog.Builder(activity).setPositiveButton(R.string.yes, (d, which) -> Utils.dataBox.delUserCookie(cookieModel)) + .setNegativeButton(R.string.no, null).setMessage(getString(R.string.quick_access_confirm_delete, + cookieModel.getUsername())).show(); + } + + return true; + } + + @Override + public void onDismiss(@NonNull final DialogInterface dialog) { + super.onDismiss(dialog); + if (cookieChanged && activity != null) activity.recreate(); + } + + @Override + public void onShow(final DialogInterface dialog) { + if (settingsHelper.getBoolean(Constants.SHOW_QUICK_ACCESS_DIALOG)) + new AlertDialog.Builder(activity) + .setMessage(R.string.quick_access_info_dialog) + .setPositiveButton(R.string.ok, null) + .setNeutralButton(R.string.dont_show_again, (d, which) -> + settingsHelper.putBoolean(Constants.SHOW_QUICK_ACCESS_DIALOG, false)).show(); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/dialogs/SettingsDialog.java b/app/src/main/java/awais/instagrabber/dialogs/SettingsDialog.java new file mode 100755 index 00000000..5b116cd8 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/dialogs/SettingsDialog.java @@ -0,0 +1,213 @@ +package awais.instagrabber.dialogs; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.CompoundButton; +import android.widget.Spinner; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatCheckBox; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.FragmentManager; + +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; + +import awais.instagrabber.R; +import awais.instagrabber.activities.Login; +import awais.instagrabber.utils.DirectoryChooser; +import awais.instagrabber.utils.LocaleUtils; +import awais.instagrabber.utils.Utils; +import awaisomereport.CrashReporter; + +import static awais.instagrabber.utils.Constants.APP_LANGUAGE; +import static awais.instagrabber.utils.Constants.APP_THEME; +import static awais.instagrabber.utils.Constants.AUTOLOAD_POSTS; +import static awais.instagrabber.utils.Constants.AUTOPLAY_VIDEOS; +import static awais.instagrabber.utils.Constants.BOTTOM_TOOLBAR; +import static awais.instagrabber.utils.Constants.DOWNLOAD_USER_FOLDER; +import static awais.instagrabber.utils.Constants.FOLDER_PATH; +import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO; +import static awais.instagrabber.utils.Constants.MUTED_VIDEOS; +import static awais.instagrabber.utils.Constants.SHOW_FEED; +import static awais.instagrabber.utils.Utils.settingsHelper; + +public final class SettingsDialog extends BottomSheetDialogFragment implements View.OnClickListener, AdapterView.OnItemSelectedListener, + CompoundButton.OnCheckedChangeListener { + private Activity activity; + private FragmentManager fragmentManager; + private View btnSaveTo, btnImportExport, btnLogin, btnTimeSettings, btnReport; + private Spinner spAppTheme, spLanguage; + private boolean somethingChanged = false; + private int currentTheme, currentLanguage, selectedLanguage; + + @Override + public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) { + if (requestCode != 6200) return; + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) showDirectoryChooser(); + else Toast.makeText(activity, R.string.direct_download_perms_ask, Toast.LENGTH_SHORT).show(); + } + + private void showDirectoryChooser() { + FragmentManager fragmentManager = getFragmentManager(); + if (fragmentManager == null) fragmentManager = getChildFragmentManager(); + + new DirectoryChooser().setInitialDirectory(settingsHelper.getString(FOLDER_PATH)) + .setInteractionListener(path -> { + settingsHelper.putString(FOLDER_PATH, path); + somethingChanged = true; + }).show(fragmentManager, null); + } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) { + final Dialog dialog = super.onCreateDialog(savedInstanceState); + + final Context context = getContext(); + activity = context instanceof Activity ? (Activity) context : getActivity(); + + fragmentManager = getFragmentManager(); + if (fragmentManager == null) fragmentManager = getChildFragmentManager(); + + final View contentView = View.inflate(activity, R.layout.dialog_main_settings, null); + + btnLogin = contentView.findViewById(R.id.btnLogin); + btnSaveTo = contentView.findViewById(R.id.btnSaveTo); + btnImportExport = contentView.findViewById(R.id.importExport); + btnTimeSettings = contentView.findViewById(R.id.btnTimeSettings); + btnReport = contentView.findViewById(R.id.btnReport); + + Utils.setTooltipText(btnImportExport, R.string.import_export); + + btnLogin.setOnClickListener(this); + btnReport.setOnClickListener(this); + btnSaveTo.setOnClickListener(this); + btnImportExport.setOnClickListener(this); + btnTimeSettings.setOnClickListener(this); + + spAppTheme = contentView.findViewById(R.id.spAppTheme); + currentTheme = settingsHelper.getInteger(APP_THEME); + spAppTheme.setSelection(currentTheme); + spAppTheme.setOnItemSelectedListener(this); + + spLanguage = contentView.findViewById(R.id.spLanguage); + currentLanguage = settingsHelper.getInteger(APP_LANGUAGE); + spLanguage.setSelection(currentLanguage); + spLanguage.setOnItemSelectedListener(this); + + final AppCompatCheckBox cbSaveTo = contentView.findViewById(R.id.cbSaveTo); + final AppCompatCheckBox cbShowFeed = contentView.findViewById(R.id.cbShowFeed); + final AppCompatCheckBox cbMuteVideos = contentView.findViewById(R.id.cbMuteVideos); + final AppCompatCheckBox cbBottomToolbar = contentView.findViewById(R.id.cbBottomToolbar); + final AppCompatCheckBox cbAutoloadPosts = contentView.findViewById(R.id.cbAutoloadPosts); + final AppCompatCheckBox cbAutoplayVideos = contentView.findViewById(R.id.cbAutoplayVideos); + final AppCompatCheckBox cbDownloadUsername = contentView.findViewById(R.id.cbDownloadUsername); + + cbSaveTo.setChecked(settingsHelper.getBoolean(FOLDER_SAVE_TO)); + cbMuteVideos.setChecked(settingsHelper.getBoolean(MUTED_VIDEOS)); + cbBottomToolbar.setChecked(settingsHelper.getBoolean(BOTTOM_TOOLBAR)); + cbAutoplayVideos.setChecked(settingsHelper.getBoolean(AUTOPLAY_VIDEOS)); + + cbShowFeed.setChecked(settingsHelper.getBoolean(SHOW_FEED)); + cbAutoloadPosts.setChecked(settingsHelper.getBoolean(AUTOLOAD_POSTS)); + cbDownloadUsername.setChecked(settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER)); + + setupListener(cbSaveTo); + setupListener(cbShowFeed); + setupListener(cbMuteVideos); + setupListener(cbBottomToolbar); + setupListener(cbAutoloadPosts); + setupListener(cbAutoplayVideos); + setupListener(cbDownloadUsername); + + btnSaveTo.setEnabled(cbSaveTo.isChecked()); + + dialog.setContentView(contentView); + + return dialog; + } + + private void setupListener(@NonNull final AppCompatCheckBox checkBox) { + checkBox.setOnCheckedChangeListener(this); + ((View) checkBox.getParent()).setOnClickListener(this); + } + + @Override + public void onItemSelected(final AdapterView spinner, final View view, final int position, final long id) { + if (spinner == spAppTheme) { + if (position != currentTheme) { + settingsHelper.putInteger(APP_THEME, position); + somethingChanged = true; + } + } else if (spinner == spLanguage) { + selectedLanguage = position; + if (position != currentLanguage) { + settingsHelper.putInteger(APP_LANGUAGE, position); + somethingChanged = true; + } + } + } + + @Override + public void onClick(final View v) { + if (v == btnLogin) { + startActivity(new Intent(v.getContext(), Login.class)); + somethingChanged = true; + + } else if (v == btnImportExport) { + if (ContextCompat.checkSelfPermission(activity, Utils.PERMS[0]) == PackageManager.PERMISSION_DENIED) + requestPermissions(Utils.PERMS, 6007); + else Utils.showImportExportDialog(activity); + + } else if (v == btnTimeSettings) { + new TimeSettingsDialog().show(fragmentManager, null); + + } else if (v == btnReport) { + CrashReporter.get(activity.getApplication()).zipLogs().startCrashEmailIntent(activity, true); + + } else if (v == btnSaveTo) { + if (ContextCompat.checkSelfPermission(activity, Utils.PERMS[0]) == PackageManager.PERMISSION_DENIED) + requestPermissions(Utils.PERMS, 6200); + else showDirectoryChooser(); + + } else if (v instanceof ViewGroup) + ((ViewGroup) v).getChildAt(0).performClick(); + } + + @Override + public void onCheckedChanged(@NonNull final CompoundButton checkBox, final boolean checked) { + final int id = checkBox.getId(); + if (id == R.id.cbDownloadUsername) settingsHelper.putBoolean(DOWNLOAD_USER_FOLDER, checked); + else if (id == R.id.cbBottomToolbar) settingsHelper.putBoolean(BOTTOM_TOOLBAR, checked); + else if (id == R.id.cbAutoplayVideos) settingsHelper.putBoolean(AUTOPLAY_VIDEOS, checked); + else if (id == R.id.cbMuteVideos) settingsHelper.putBoolean(MUTED_VIDEOS, checked); + else if (id == R.id.cbAutoloadPosts) settingsHelper.putBoolean(AUTOLOAD_POSTS, checked); + else if (id == R.id.cbShowFeed) settingsHelper.putBoolean(SHOW_FEED, checked); + else if (id == R.id.cbSaveTo) { + settingsHelper.putBoolean(FOLDER_SAVE_TO, checked); + btnSaveTo.setEnabled(checked); + } + somethingChanged = true; + } + + @Override + public void onDismiss(@NonNull final DialogInterface dialog) { + if (selectedLanguage != currentLanguage) + LocaleUtils.setLocale(activity != null ? activity.getBaseContext() : getLayoutInflater().getContext().getApplicationContext()); + super.onDismiss(dialog); + if (somethingChanged && activity != null) activity.recreate(); + } + + @Override + public void onNothingSelected(final AdapterView parent) { } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/dialogs/TimeSettingsDialog.java b/app/src/main/java/awais/instagrabber/dialogs/TimeSettingsDialog.java new file mode 100755 index 00000000..f9225d9f --- /dev/null +++ b/app/src/main/java/awais/instagrabber/dialogs/TimeSettingsDialog.java @@ -0,0 +1,173 @@ +package awais.instagrabber.dialogs; + +import android.app.Dialog; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.AdapterView; +import android.widget.CompoundButton; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +import awais.instagrabber.databinding.DialogTimeSettingsBinding; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.LocaleUtils; +import awais.instagrabber.utils.Utils; + +import static awais.instagrabber.utils.Utils.settingsHelper; + +public final class TimeSettingsDialog extends DialogFragment implements AdapterView.OnItemSelectedListener, CompoundButton.OnCheckedChangeListener, + View.OnClickListener, TextWatcher { + private DialogTimeSettingsBinding timeSettingsBinding; + private final Date magicDate; + private SimpleDateFormat currentFormat; + private String selectedFormat; + + public TimeSettingsDialog() { + super(); + final Calendar instance = GregorianCalendar.getInstance(); + instance.set(2020, 5, 22, 8, 17, 13); + magicDate = instance.getTime(); + } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) { + final Dialog dialog = super.onCreateDialog(savedInstanceState); + timeSettingsBinding = DialogTimeSettingsBinding.inflate(LayoutInflater.from(getContext())); + + timeSettingsBinding.cbCustomFormat.setOnCheckedChangeListener(this); + + timeSettingsBinding.cbCustomFormat.setChecked(settingsHelper.getBoolean(Constants.CUSTOM_DATE_TIME_FORMAT_ENABLED)); + timeSettingsBinding.etCustomFormat.setText(settingsHelper.getString(Constants.CUSTOM_DATE_TIME_FORMAT)); + + final String[] dateTimeFormat = settingsHelper.getString(Constants.DATE_TIME_SELECTION).split(";"); // output = time;separator;date + timeSettingsBinding.spTimeFormat.setSelection(Integer.parseInt(dateTimeFormat[0])); + timeSettingsBinding.spSeparator.setSelection(Integer.parseInt(dateTimeFormat[1])); + timeSettingsBinding.spDateFormat.setSelection(Integer.parseInt(dateTimeFormat[2])); + + timeSettingsBinding.cbSwapTimeDate.setOnCheckedChangeListener(this); + + refreshTimeFormat(); + + timeSettingsBinding.spTimeFormat.setOnItemSelectedListener(this); + timeSettingsBinding.spDateFormat.setOnItemSelectedListener(this); + timeSettingsBinding.spSeparator.setOnItemSelectedListener(this); + + timeSettingsBinding.etCustomFormat.addTextChangedListener(this); + timeSettingsBinding.btnConfirm.setOnClickListener(this); + timeSettingsBinding.btnInfo.setOnClickListener(this); + + dialog.setContentView(timeSettingsBinding.getRoot()); + return dialog; + } + + private void refreshTimeFormat() { + if (timeSettingsBinding.cbCustomFormat.isChecked()) { + timeSettingsBinding.btnConfirm.setEnabled(false); + checkCustomTimeFormat(); + } else { + final String sepStr = String.valueOf(timeSettingsBinding.spSeparator.getSelectedItem()); + final String timeStr = String.valueOf(timeSettingsBinding.spTimeFormat.getSelectedItem()); + final String dateStr = String.valueOf(timeSettingsBinding.spDateFormat.getSelectedItem()); + + final boolean isSwapTime = !timeSettingsBinding.cbSwapTimeDate.isChecked(); + + selectedFormat = (isSwapTime ? timeStr : dateStr) + + (Utils.isEmpty(sepStr) || timeSettingsBinding.spSeparator.getSelectedItemPosition() == 0 ? " " : " '" + sepStr + "' ") + + (isSwapTime ? dateStr : timeStr); + + timeSettingsBinding.btnConfirm.setEnabled(true); + timeSettingsBinding.timePreview.setText((currentFormat = new SimpleDateFormat(selectedFormat, LocaleUtils.getCurrentLocale())).format(magicDate)); + } + } + + private void checkCustomTimeFormat() { + try { + //noinspection ConstantConditions + final String string = timeSettingsBinding.etCustomFormat.getText().toString(); + if (Utils.isEmpty(string)) throw new NullPointerException(); + + final String format = (currentFormat = new SimpleDateFormat(string, LocaleUtils.getCurrentLocale())).format(magicDate); + timeSettingsBinding.timePreview.setText(format); + + timeSettingsBinding.btnConfirm.setEnabled(true); + } catch (final Exception e) { + timeSettingsBinding.btnConfirm.setEnabled(false); + timeSettingsBinding.timePreview.setText(null); + } + } + + @Override + public void onItemSelected(final AdapterView p, final View v, final int pos, final long id) { + refreshTimeFormat(); + } + + @Override + public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) { + if (buttonView == timeSettingsBinding.cbCustomFormat) { + timeSettingsBinding.etCustomFormat.setEnabled(isChecked); + timeSettingsBinding.btnInfo.setEnabled(isChecked); + + timeSettingsBinding.spTimeFormat.setEnabled(!isChecked); + timeSettingsBinding.spDateFormat.setEnabled(!isChecked); + timeSettingsBinding.spSeparator.setEnabled(!isChecked); + timeSettingsBinding.cbSwapTimeDate.setEnabled(!isChecked); + } + refreshTimeFormat(); + } + + @Override + public void onTextChanged(final CharSequence s, final int start, final int before, final int count) { + checkCustomTimeFormat(); + } + + @Override + public void onClick(final View v) { + if (v == timeSettingsBinding.btnConfirm) { + final String formatSelection; + + final boolean isCustomFormat = timeSettingsBinding.cbCustomFormat.isChecked(); + + if (isCustomFormat) { + //noinspection ConstantConditions + formatSelection = timeSettingsBinding.etCustomFormat.getText().toString(); + settingsHelper.putString(Constants.CUSTOM_DATE_TIME_FORMAT, formatSelection); + } else { + formatSelection = timeSettingsBinding.spTimeFormat.getSelectedItemPosition() + ";" + + timeSettingsBinding.spSeparator.getSelectedItemPosition() + ';' + + timeSettingsBinding.spDateFormat.getSelectedItemPosition(); // time;separator;date + + settingsHelper.putString(Constants.DATE_TIME_FORMAT, selectedFormat); + settingsHelper.putString(Constants.DATE_TIME_SELECTION, formatSelection); + } + + settingsHelper.putBoolean(Constants.CUSTOM_DATE_TIME_FORMAT_ENABLED, isCustomFormat); + + Utils.datetimeParser = (SimpleDateFormat) currentFormat.clone(); + dismiss(); + } else if (v == timeSettingsBinding.btnInfo) { + timeSettingsBinding.customPanel.setVisibility(timeSettingsBinding.customPanel + .getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE); + + } + } + + @Override + public void onNothingSelected(final AdapterView parent) { } + + @Override + public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) { } + + @Override + public void afterTextChanged(final Editable s) { } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/directdownload/DirectDownload.java b/app/src/main/java/awais/instagrabber/directdownload/DirectDownload.java new file mode 100755 index 00000000..005fda27 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/directdownload/DirectDownload.java @@ -0,0 +1,153 @@ +package awais.instagrabber.directdownload; + +import android.Manifest; +import android.app.Activity; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.view.WindowManager; +import android.widget.Toast; + +import androidx.core.app.ActivityCompat; +import androidx.core.app.NotificationCompat; +import androidx.core.app.NotificationManagerCompat; +import androidx.core.content.ContextCompat; + +import java.util.Arrays; + +import awais.instagrabber.R; +import awais.instagrabber.asyncs.PostFetcher; +import awais.instagrabber.interfaces.FetchListener; +import awais.instagrabber.models.IntentModel; +import awais.instagrabber.models.ViewerPostModel; +import awais.instagrabber.models.enums.DownloadMethod; +import awais.instagrabber.models.enums.IntentModelType; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; + +import static awais.instagrabber.utils.Utils.CHANNEL_ID; +import static awais.instagrabber.utils.Utils.CHANNEL_NAME; +import static awais.instagrabber.utils.Utils.isChannelCreated; +import static awais.instagrabber.utils.Utils.notificationManager; + +public final class DirectDownload extends Activity { + private boolean isFound = false; + private Intent intent; + private Context context; + + @Override + public void onWindowAttributesChanged(final WindowManager.LayoutParams params) { + super.onWindowAttributesChanged(params); + if (!isFound) { + intent = getIntent(); + context = getApplicationContext(); + if (intent != null && context != null) { + isFound = true; + checkIntent(); + } + } + } + + @Override + public Resources getResources() { + if (!isFound) { + intent = getIntent(); + context = getApplicationContext(); + if (intent != null && context != null) { + isFound = true; + checkIntent(); + } + } + return super.getResources(); + } + + private synchronized void checkIntent() { + if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) + doDownload(); + else { + final Handler handler = new Handler(Looper.getMainLooper()); + handler.post(new Runnable() { + @Override + public void run() { + Toast.makeText(context, R.string.direct_download_perms_ask, Toast.LENGTH_LONG).show(); + handler.removeCallbacks(this); + } + }); + ActivityCompat.requestPermissions(this, Utils.PERMS, 8020); + } + finish(); + } + + private synchronized void doDownload() { + final String action = intent.getAction(); + if (!Utils.isEmpty(action) && !Intent.ACTION_MAIN.equals(action)) { + boolean error = true; + + String data = null; + final Bundle extras = intent.getExtras(); + if (extras != null) { + final Object extraData = extras.get(Intent.EXTRA_TEXT); + if (extraData != null) { + error = false; + data = extraData.toString(); + } + } + + if (error) { + final Uri intentData = intent.getData(); + if (intentData != null) data = intentData.toString(); + } + + if (data != null && !Utils.isEmpty(data)) { + final IntentModel model = Utils.stripString(data); + if (model != null && model.getType() == IntentModelType.POST) { + final String text = model.getText(); + + new PostFetcher(text, new FetchListener() { + @Override + public void doBefore() { + if (notificationManager == null) + notificationManager = NotificationManagerCompat.from(context.getApplicationContext()); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !isChannelCreated) { + notificationManager.createNotificationChannel(new NotificationChannel(CHANNEL_ID, + CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH)); + isChannelCreated = true; + } + final Notification fetchingPostNotif = new NotificationCompat.Builder(context, CHANNEL_ID) + .setCategory(NotificationCompat.CATEGORY_STATUS).setSmallIcon(R.mipmap.ic_launcher) + .setAutoCancel(false).setPriority(NotificationCompat.PRIORITY_MIN) + .setContentText(context.getString(R.string.direct_download_loading)).build(); + notificationManager.notify(1900000000, fetchingPostNotif); + } + + @Override + public void onResult(final ViewerPostModel[] result) { + if (notificationManager != null) notificationManager.cancel(1900000000); + if (result != null) { + if (result.length == 1) { + Utils.batchDownload(context, result[0].getUsername(), DownloadMethod.DOWNLOAD_DIRECT, + Arrays.asList(result)); + } else if (result.length > 1) { + context.startActivity(new Intent(context, MultiDirectDialog.class) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) + .putExtra(Constants.EXTRAS_POST, result)); + } + } + } + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/directdownload/MultiDirectDialog.java b/app/src/main/java/awais/instagrabber/directdownload/MultiDirectDialog.java new file mode 100755 index 00000000..86bb7150 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/directdownload/MultiDirectDialog.java @@ -0,0 +1,117 @@ +package awais.instagrabber.directdownload; + +import android.content.Intent; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.Toolbar; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; +import java.util.Collections; + +import awais.instagrabber.R; +import awais.instagrabber.activities.BaseLanguageActivity; +import awais.instagrabber.adapters.PostsAdapter; +import awais.instagrabber.customviews.helpers.GridAutofitLayoutManager; +import awais.instagrabber.customviews.helpers.GridSpacingItemDecoration; +import awais.instagrabber.models.BasePostModel; +import awais.instagrabber.models.PostModel; +import awais.instagrabber.models.ViewerPostModel; +import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.Utils; +import awais.instagrabber.models.enums.DownloadMethod; + +public final class MultiDirectDialog extends BaseLanguageActivity { + public final ArrayList selectedItems = new ArrayList<>(); + private PostsAdapter postsAdapter; + private MenuItem btnDownload; + private String username = null; + + @Override + protected void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_direct); + + final Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + final ViewerPostModel[] postModels; + final Intent intent = getIntent(); + if (intent == null || !intent.hasExtra(Constants.EXTRAS_POST) + || (postModels = (ViewerPostModel[]) intent.getSerializableExtra(Constants.EXTRAS_POST)) == null) { + Utils.errorFinish(this); + return; + } + + username = postModels[0].getUsername(); + toolbar.setTitle(username); + toolbar.setSubtitle(postModels[0].getShortCode()); + + final RecyclerView recyclerView = findViewById(R.id.mainPosts); + recyclerView.setNestedScrollingEnabled(false); + recyclerView.setLayoutManager(new GridAutofitLayoutManager(this, Utils.convertDpToPx(130))); + recyclerView.addItemDecoration(new GridSpacingItemDecoration(Utils.convertDpToPx(4))); + + final ArrayList models = new ArrayList<>(postModels.length - 1); + for (final ViewerPostModel postModel : postModels) + models.add(new PostModel(postModel.getItemType(), postModel.getPostId(), postModel.getDisplayUrl(), + postModel.getSliderDisplayUrl(), postModel.getShortCode(), postModel.getPostCaption(), postModel.getTimestamp())); + + postsAdapter = new PostsAdapter(models, v -> { + final Object tag = v.getTag(); + if (tag instanceof PostModel) { + final PostModel postModel = (PostModel) tag; + if (postsAdapter.isSelecting) toggleSelection(postModel); + else { + Utils.batchDownload(this, username, DownloadMethod.DOWNLOAD_DIRECT, Collections.singletonList(postModel)); + finish(); + } + } + }, v -> { + final Object tag = v.getTag(); + if (tag instanceof PostModel) { + postsAdapter.isSelecting = true; + toggleSelection((PostModel) tag); + } + return true; + }); + + recyclerView.setAdapter(postsAdapter); + } + + @Override + public boolean onOptionsItemSelected(@NonNull final MenuItem item) { + Utils.batchDownload(this, username, DownloadMethod.DOWNLOAD_DIRECT, selectedItems); + finish(); + return true; + } + + @Override + public boolean onCreateOptionsMenu(final Menu menu) { + getMenuInflater().inflate(R.menu.menu, menu); + btnDownload = menu.findItem(R.id.action_download); + menu.findItem(R.id.action_search).setVisible(false); + return true; + } + + private void toggleSelection(final PostModel postModel) { + if (postModel != null && postsAdapter != null) { + if (postModel.isSelected()) selectedItems.remove(postModel); + else selectedItems.add(postModel); + postModel.setSelected(!postModel.isSelected()); + notifyAdapter(postModel); + } + } + + private void notifyAdapter(final PostModel postModel) { + if (selectedItems.size() < 1) postsAdapter.isSelecting = false; + if (postModel.getPosition() < 0) postsAdapter.notifyDataSetChanged(); + else postsAdapter.notifyItemChanged(postModel.getPosition(), postModel); + + if (btnDownload != null) btnDownload.setVisible(postsAdapter.isSelecting); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/interfaces/FetchListener.java b/app/src/main/java/awais/instagrabber/interfaces/FetchListener.java new file mode 100755 index 00000000..e9b43f00 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/interfaces/FetchListener.java @@ -0,0 +1,6 @@ +package awais.instagrabber.interfaces; + +public interface FetchListener { + void onResult(T result); + default void doBefore() { } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/interfaces/ItemGetter.java b/app/src/main/java/awais/instagrabber/interfaces/ItemGetter.java new file mode 100755 index 00000000..c53c2491 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/interfaces/ItemGetter.java @@ -0,0 +1,11 @@ +package awais.instagrabber.interfaces; + +import java.io.Serializable; +import java.util.List; + +import awais.instagrabber.models.BasePostModel; +import awais.instagrabber.models.enums.ItemGetType; + +public interface ItemGetter extends Serializable { + List get(final ItemGetType itemGetType); +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/interfaces/LazyLoadListener.java b/app/src/main/java/awais/instagrabber/interfaces/LazyLoadListener.java new file mode 100755 index 00000000..ca98a3f1 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/interfaces/LazyLoadListener.java @@ -0,0 +1,5 @@ +package awais.instagrabber.interfaces; + +public interface LazyLoadListener { + void onLoadMore(final int page, final int totalItemsCount); +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/interfaces/MentionClickListener.java b/app/src/main/java/awais/instagrabber/interfaces/MentionClickListener.java new file mode 100755 index 00000000..d8d0a347 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/interfaces/MentionClickListener.java @@ -0,0 +1,7 @@ +package awais.instagrabber.interfaces; + +import awais.instagrabber.customviews.RamboTextView; + +public interface MentionClickListener { + void onClick(final RamboTextView view, final String text, final boolean isHashtag); +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/interfaces/OnGroupClickListener.java b/app/src/main/java/awais/instagrabber/interfaces/OnGroupClickListener.java new file mode 100755 index 00000000..d7763851 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/interfaces/OnGroupClickListener.java @@ -0,0 +1,5 @@ +package awais.instagrabber.interfaces; + +public interface OnGroupClickListener { + void toggleGroup(final int flatPos); +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/interfaces/SwipeEvent.java b/app/src/main/java/awais/instagrabber/interfaces/SwipeEvent.java new file mode 100755 index 00000000..89eba321 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/interfaces/SwipeEvent.java @@ -0,0 +1,5 @@ +package awais.instagrabber.interfaces; + +public interface SwipeEvent { + void onSwipe(final boolean isRight); +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/BasePostModel.java b/app/src/main/java/awais/instagrabber/models/BasePostModel.java new file mode 100755 index 00000000..7a0dca86 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/BasePostModel.java @@ -0,0 +1,82 @@ +package awais.instagrabber.models; + +import androidx.annotation.NonNull; + +import java.io.Serializable; +import java.util.Date; + +import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.utils.Utils; + +public abstract class BasePostModel implements Serializable { + protected String postId; + protected String displayUrl; + protected String shortCode; + protected CharSequence postCaption; + protected MediaItemType itemType; + protected boolean isSelected; + protected boolean isDownloaded; + protected long timestamp; + protected int position; + + public MediaItemType getItemType() { + return itemType; + } + + public final String getPostId() { + return postId; + } + + public final String getDisplayUrl() { + return displayUrl; + } + + public final CharSequence getPostCaption() { + return postCaption; + } + + public final String getShortCode() { + return shortCode; + } + + public final long getTimestamp() { + return timestamp; + } + + public int getPosition() { + return this.position; + } + + public boolean isSelected() { + return isSelected; + } + + public boolean isDownloaded() { + return isDownloaded; + } + + public void setItemType(final MediaItemType itemType) { + this.itemType = itemType; + } + + public void setPostId(final String postId) { + this.postId = postId; + } + + public void setPosition(final int position) { + this.position = position; + } + + public void setSelected(final boolean selected) { + this.isSelected = selected; + } + + public void setDownloaded(final boolean downloaded) { + isDownloaded = downloaded; + } + + @NonNull + public final String getPostDate() { + return Utils.datetimeParser.format(new Date(timestamp * 1000L)); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/CommentModel.java b/app/src/main/java/awais/instagrabber/models/CommentModel.java new file mode 100755 index 00000000..130139aa --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/CommentModel.java @@ -0,0 +1,85 @@ +package awais.instagrabber.models; + +import androidx.annotation.NonNull; + +import java.util.Date; + +import awais.instagrabber.utils.Utils; + +public final class CommentModel { + private final ProfileModel profileModel; + private final String id; + private final CharSequence text; + private final long likes, timestamp; + private CommentModel[] childCommentModels; + private boolean hasNextPage; + private String endCursor; + + public CommentModel(final String id, final String text, final long timestamp, final long likes, final ProfileModel profileModel) { + this.id = id; + this.text = Utils.hasMentions(text) ? Utils.getMentionText(text) : text; + this.likes = likes; + this.timestamp = timestamp; + this.profileModel = profileModel; + } + + public String getId() { + return id; + } + + public CharSequence getText() { + return text; + } + + @NonNull + public String getDateTime() { + return Utils.datetimeParser.format(new Date(timestamp * 1000L)); + } + + public long getLikes() { + return likes; + } + + public ProfileModel getProfileModel() { + return profileModel; + } + + public CommentModel[] getChildCommentModels() { + return childCommentModels; + } + + public void setChildCommentModels(final CommentModel[] childCommentModels) { + this.childCommentModels = childCommentModels; + } + + public void setPageCursor(final boolean hasNextPage, final String endCursor) { + this.hasNextPage = hasNextPage; + this.endCursor = endCursor; + } + + public boolean hasNextPage() { + return hasNextPage; + } + + public String getEndCursor() { + return endCursor; + } + +// @NonNull +// @Override +// public String toString() { +// try { +// final JSONObject object = new JSONObject(); +// object.put(Constants.EXTRAS_ID, id); +// object.put("text", text); +// object.put(Constants.EXTRAS_NAME, profileModel != null ? profileModel.getUsername() : ""); +// if (childCommentModels != null) object.put("childComments", childCommentModels); +// return object.toString(); +// } catch (Exception e) { +// return "{\"id\":\"" + id + "\", \"text\":\"" + text +// //(text != null ? text.replaceAll("\"", "\\\\\"") : "") +// + "\", \"name\":\"" + (profileModel != null ? profileModel.getUsername() : "") + +// (childCommentModels != null ? "\", \"childComments\":" + childCommentModels.length : "\"") + '}'; +// } +// } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/DiscoverItemModel.java b/app/src/main/java/awais/instagrabber/models/DiscoverItemModel.java new file mode 100755 index 00000000..925763b8 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/DiscoverItemModel.java @@ -0,0 +1,29 @@ +package awais.instagrabber.models; + +import awais.instagrabber.models.enums.MediaItemType; + +public final class DiscoverItemModel extends BasePostModel { + private boolean moreAvailable; + private String nextMaxId; + + public DiscoverItemModel(final MediaItemType mediaType, final String postId, final String shortCode, final String thumbnail) { + this.postId = postId; + this.itemType = mediaType; + this.shortCode = shortCode; + this.displayUrl = thumbnail; + } + + + public void setMore(final boolean moreAvailable, final String nextMaxId) { + this.moreAvailable = moreAvailable; + this.nextMaxId = nextMaxId; + } + + public boolean hasMore() { + return moreAvailable; + } + + public String getNextMaxId() { + return nextMaxId; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/FeedModel.java b/app/src/main/java/awais/instagrabber/models/FeedModel.java new file mode 100755 index 00000000..b010a8d2 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/FeedModel.java @@ -0,0 +1,56 @@ +package awais.instagrabber.models; + +import awais.instagrabber.models.enums.MediaItemType; + +public final class FeedModel extends PostModel { + private final ProfileModel profileModel; + private final long commentsCount, viewCount; + private boolean captionExpanded = false, mentionClicked = false; + private ViewerPostModel[] sliderItems; + + public FeedModel(final ProfileModel profileModel, final MediaItemType itemType, final long viewCount, final String postId, + final String displayUrl, final String thumbnailUrl, final String shortCode, final String postCaption, + final long commentsCount, final long timestamp) { + super(itemType, postId, displayUrl, thumbnailUrl, shortCode, postCaption, timestamp); + this.profileModel = profileModel; + this.commentsCount = commentsCount; + this.viewCount = viewCount; + } + + public ProfileModel getProfileModel() { + return profileModel; + } + + public ViewerPostModel[] getSliderItems() { + return sliderItems; + } + + public long getViewCount() { + return viewCount; + } + + public long getCommentsCount() { + return commentsCount; + } + + public boolean isCaptionExpanded() { + return captionExpanded; + } + + public boolean isMentionClicked() { + return !mentionClicked; + } + + public void setMentionClicked(final boolean mentionClicked) { + this.mentionClicked = mentionClicked; + } + + public void setSliderItems(final ViewerPostModel[] sliderItems) { + this.sliderItems = sliderItems; + setItemType(MediaItemType.MEDIA_TYPE_SLIDER); + } + + public void toggleCaption() { + captionExpanded = !captionExpanded; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/FeedStoryModel.java b/app/src/main/java/awais/instagrabber/models/FeedStoryModel.java new file mode 100755 index 00000000..6e6e7362 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/FeedStoryModel.java @@ -0,0 +1,30 @@ +package awais.instagrabber.models; + +import java.io.Serializable; + +public final class FeedStoryModel implements Serializable { + private final String storyMediaId; + private final ProfileModel profileModel; + private StoryModel[] storyModels; + + public FeedStoryModel(final String storyMediaId, final ProfileModel profileModel) { + this.storyMediaId = storyMediaId; + this.profileModel = profileModel; + } + + public String getStoryMediaId() { + return storyMediaId; + } + + public ProfileModel getProfileModel() { + return profileModel; + } + + public void setStoryModels(final StoryModel[] storyModels) { + this.storyModels = storyModels; + } + + public StoryModel[] getStoryModels() { + return storyModels; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/FollowModel.java b/app/src/main/java/awais/instagrabber/models/FollowModel.java new file mode 100755 index 00000000..fd9cc7a4 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/FollowModel.java @@ -0,0 +1,64 @@ +package awais.instagrabber.models; + +import androidx.annotation.Nullable; + +import java.io.Serializable; + +public final class FollowModel implements Serializable { + private final String id, username, fullName, profilePicUrl; + private String endCursor; + private boolean hasNextPage, isShown = true; + + public FollowModel(final String id, final String username, final String fullName, final String profilePicUrl) { + this.id = id; + this.username = username; + this.fullName = fullName; + this.profilePicUrl = profilePicUrl; + } + + public String getId() { + return id; + } + + public String getUsername() { + return username; + } + + public String getFullName() { + return fullName; + } + + public String getProfilePicUrl() { + return profilePicUrl; + } + + public boolean isShown() { + return isShown; + } + + public void setShown(final boolean shown) { + isShown = shown; + } + + public void setPageCursor(final boolean hasNextPage, final String endCursor) { + this.endCursor = endCursor; + this.hasNextPage = hasNextPage; + } + + public boolean hasNextPage() { + return endCursor != null && hasNextPage; + } + + public String getEndCursor() { + return endCursor; + } + + @Override + public boolean equals(@Nullable final Object obj) { + if (obj instanceof FollowModel) { + final FollowModel model = (FollowModel) obj; + if (model.getId().equals(id) && model.getUsername().equals(username)) return true; + } + return super.equals(obj); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/HighlightModel.java b/app/src/main/java/awais/instagrabber/models/HighlightModel.java new file mode 100755 index 00000000..d7af017a --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/HighlightModel.java @@ -0,0 +1,27 @@ +package awais.instagrabber.models; + +public final class HighlightModel { + private final String title, thumbnailUrl; + private StoryModel[] storyModels; + + public HighlightModel(final String title, final String thumbnailUrl) { + this.title = title; + this.thumbnailUrl = thumbnailUrl; + } + + public String getTitle() { + return title; + } + + public String getThumbnailUrl() { + return thumbnailUrl; + } + + public StoryModel[] getStoryModels() { + return storyModels; + } + + public void setStoryModels(final StoryModel[] storyModels) { + this.storyModels = storyModels; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/IntentModel.java b/app/src/main/java/awais/instagrabber/models/IntentModel.java new file mode 100755 index 00000000..3348bb2e --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/IntentModel.java @@ -0,0 +1,21 @@ +package awais.instagrabber.models; + +import awais.instagrabber.models.enums.IntentModelType; + +public final class IntentModel { + private final IntentModelType type; + private final String text; + + public IntentModel(final IntentModelType type, final String text) { + this.type = type; + this.text = text; + } + + public IntentModelType getType() { + return type; + } + + public String getText() { + return text; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/PostModel.java b/app/src/main/java/awais/instagrabber/models/PostModel.java new file mode 100755 index 00000000..ad8550c3 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/PostModel.java @@ -0,0 +1,50 @@ +package awais.instagrabber.models; + +import awais.instagrabber.models.enums.MediaItemType; + +public class PostModel extends BasePostModel { + protected final String thumbnailUrl; + protected String endCursor; + protected boolean hasNextPage; + + public PostModel(final String shortCode) { + this.shortCode = shortCode; + this.thumbnailUrl = null; + } + + public PostModel(final MediaItemType itemType, final String postId, final String displayUrl, final String thumbnailUrl, + final String shortCode, final CharSequence postCaption, long timestamp) { + this.itemType = itemType; + this.postId = postId; + this.displayUrl = displayUrl; + this.thumbnailUrl = thumbnailUrl; + this.shortCode = shortCode; + this.postCaption = postCaption; + this.timestamp = timestamp; + } + + public String getThumbnailUrl() { + return thumbnailUrl; + } + + public String getEndCursor() { + return endCursor; + } + + public boolean hasNextPage() { + return endCursor != null && hasNextPage; + } + + public void setPostCaption(final CharSequence postCaption) { + this.postCaption = postCaption; + } + + public void setTimestamp(final long timestamp) { + this.timestamp = timestamp; + } + + public void setPageCursor(final boolean hasNextPage, final String endCursor) { + this.endCursor = endCursor; + this.hasNextPage = hasNextPage; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/ProfileModel.java b/app/src/main/java/awais/instagrabber/models/ProfileModel.java new file mode 100755 index 00000000..43989209 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/ProfileModel.java @@ -0,0 +1,75 @@ +package awais.instagrabber.models; + +import java.io.Serializable; + +public final class ProfileModel implements Serializable { + private final boolean isPrivate, isVerified; + private final long postCount, followersCount, followingCount; + private final String id, username, name, biography, url, sdProfilePic, hdProfilePic; + + public ProfileModel(final boolean isPrivate, final boolean isVerified, final String id, final String username, + final String name, final String biography, final String url, final String sdProfilePic, final String hdProfilePic, + final long postCount, final long followersCount, final long followingCount) { + this.isPrivate = isPrivate; + this.isVerified = isVerified; + this.id = id; + this.url = url; + this.name = name; + this.username = username; + this.biography = biography; + this.sdProfilePic = sdProfilePic; + this.hdProfilePic = hdProfilePic; + this.postCount = postCount; + this.followersCount = followersCount; + this.followingCount = followingCount; + } + + public boolean isPrivate() { + return isPrivate; + } + + public boolean isVerified() { + return isVerified; + } + + public String getId() { + return id; + } + + public String getUsername() { + return username; + } + + public String getName() { + return name; + } + + public String getBiography() { + return biography; + } + + public String getUrl() { + return url; + } + + public String getSdProfilePic() { + return sdProfilePic; + } + + public String getHdProfilePic() { + return hdProfilePic; + } + + public long getPostCount() { + return postCount; + } + + public long getFollowersCount() { + return followersCount; + } + + public long getFollowingCount() { + return followingCount; + } + +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/StoryModel.java b/app/src/main/java/awais/instagrabber/models/StoryModel.java new file mode 100755 index 00000000..9ebed24f --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/StoryModel.java @@ -0,0 +1,69 @@ +package awais.instagrabber.models; + +import java.io.Serializable; + +import awais.instagrabber.models.enums.MediaItemType; + +public final class StoryModel implements Serializable { + private final String storyMediaId, storyUrl; + private final MediaItemType itemType; + private final long timestamp; + private String videoUrl, tappableShortCode; + private int position; + private boolean isCurrentSlide = false; + + public StoryModel(final String storyMediaId, final String storyUrl, final MediaItemType itemType, final long timestamp) { + this.storyMediaId = storyMediaId; + this.storyUrl = storyUrl; + this.itemType = itemType; + this.timestamp = timestamp; + } + + public String getStoryUrl() { + return storyUrl; + } + + public String getStoryMediaId() { + return storyMediaId; + } + + public MediaItemType getItemType() { + return itemType; + } + + public long getTimestamp() { + return timestamp; + } + + public String getVideoUrl() { + return videoUrl; + } + + public String getTappableShortCode() { + return tappableShortCode; + } + + public int getPosition() { + return position; + } + + public void setVideoUrl(final String videoUrl) { + this.videoUrl = videoUrl; + } + + public void setTappableShortCode(final String tappableShortCode) { + this.tappableShortCode = tappableShortCode; + } + + public void setPosition(final int position) { + this.position = position; + } + + public void setCurrentSlide(final boolean currentSlide) { + this.isCurrentSlide = currentSlide; + } + + public boolean isCurrentSlide() { + return isCurrentSlide; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/SuggestionModel.java b/app/src/main/java/awais/instagrabber/models/SuggestionModel.java new file mode 100755 index 00000000..855b1d4b --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/SuggestionModel.java @@ -0,0 +1,51 @@ +package awais.instagrabber.models; + +import androidx.annotation.NonNull; + +import awais.instagrabber.models.enums.SuggestionType; + +public final class SuggestionModel implements Comparable { + private final int position; + private final boolean isVerified; + private final String username, name, profilePic; + private final SuggestionType suggestionType; + + public SuggestionModel(final boolean isVerified, final String username, final String name, final String profilePic, + final SuggestionType suggestionType, final int position) { + this.isVerified = isVerified; + this.username = username; + this.name = name; + this.profilePic = profilePic; + this.suggestionType = suggestionType; + this.position = position; + } + + public boolean isVerified() { + return isVerified; + } + + public String getUsername() { + return username; + } + + public String getName() { + return name; + } + + public String getProfilePic() { + return profilePic; + } + + public SuggestionType getSuggestionType() { + return suggestionType; + } + + public int getPosition() { + return position; + } + + @Override + public int compareTo(@NonNull final SuggestionModel model) { + return Integer.compare(getPosition(), model.getPosition()); + } +} diff --git a/app/src/main/java/awais/instagrabber/models/ViewerPostModel.java b/app/src/main/java/awais/instagrabber/models/ViewerPostModel.java new file mode 100755 index 00000000..13271006 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/ViewerPostModel.java @@ -0,0 +1,63 @@ +package awais.instagrabber.models; + +import awais.instagrabber.models.enums.MediaItemType; + +public final class ViewerPostModel extends BasePostModel { + protected final String username; + protected final long videoViews; + protected String sliderDisplayUrl, commentsEndCursor; + protected long commentsCount; + private boolean isCurrentSlide = false; + + public ViewerPostModel(final MediaItemType itemType, final String postId, final String displayUrl, final String shortCode, + final String postCaption, final String username, final long videoViews, final long timestamp) { + this.itemType = itemType; + this.postId = postId; + this.displayUrl = displayUrl; + this.postCaption = postCaption; + this.username = username; + this.shortCode = shortCode; + this.videoViews = videoViews; + this.timestamp = timestamp; + } + + public long getCommentsCount() { + return commentsCount; + } + + public String getSliderDisplayUrl() { + return sliderDisplayUrl; + } + + public String getUsername() { + return username; + } + + public String getCommentsEndCursor() { + return commentsEndCursor; + } + + public final long getVideoViews() { + return videoViews; + } + + public void setSliderDisplayUrl(final String sliderDisplayUrl) { + this.sliderDisplayUrl = sliderDisplayUrl; + } + + public void setCommentsCount(final long commentsCount) { + this.commentsCount = commentsCount; + } + + public void setCommentsEndCursor(final String commentsEndCursor) { + this.commentsEndCursor = commentsEndCursor; + } + + public void setCurrentSlide(final boolean currentSlide) { + this.isCurrentSlide = currentSlide; + } + + public boolean isCurrentSlide() { + return isCurrentSlide; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/direct_messages/DirectItemModel.java b/app/src/main/java/awais/instagrabber/models/direct_messages/DirectItemModel.java new file mode 100755 index 00000000..87e82d8b --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/direct_messages/DirectItemModel.java @@ -0,0 +1,490 @@ +package awais.instagrabber.models.direct_messages; + +import androidx.annotation.NonNull; + +import java.io.Serializable; +import java.util.Date; + +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.models.enums.DirectItemType; +import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.models.enums.RavenExpiringMediaType; +import awais.instagrabber.models.enums.RavenMediaViewType; +import awais.instagrabber.utils.Utils; + +public final class DirectItemModel implements Serializable, Comparable { + private final long userId, timestamp; + private final DirectItemType itemType; + private final String itemId; + private final CharSequence text; + private final DirectItemLinkModel linkModel; + private final DirectItemMediaModel mediaModel; + private final ProfileModel profileModel; + private final DirectItemReelShareModel reelShare; + private final DirectItemActionLogModel actionLogModel; + private final DirectItemVoiceMediaModel voiceMediaModel; + private final DirectItemRavenMediaModel ravenMediaModel; + private final DirectItemAnimatedMediaModel animatedMediaModel; + private final DirectItemVideoCallEventModel videoCallEventModel; + + public DirectItemModel(final long userId, final long timestamp, final String itemId, final DirectItemType itemType, + final CharSequence text, final DirectItemLinkModel linkModel, final ProfileModel profileModel, + final DirectItemReelShareModel reelShare, final DirectItemMediaModel mediaModel, + final DirectItemActionLogModel actionLogModel, final DirectItemVoiceMediaModel voiceMediaModel, + final DirectItemRavenMediaModel ravenMediaModel, final DirectItemVideoCallEventModel videoCallEventModel, + final DirectItemAnimatedMediaModel animatedMediaModel) { + this.userId = userId; + this.timestamp = timestamp; + this.itemType = itemType; + this.itemId = itemId; + this.text = text; + this.linkModel = linkModel; + this.profileModel = profileModel; + this.reelShare = reelShare; + this.mediaModel = mediaModel; + this.actionLogModel = actionLogModel; + this.voiceMediaModel = voiceMediaModel; + this.ravenMediaModel = ravenMediaModel; + this.videoCallEventModel = videoCallEventModel; + this.animatedMediaModel = animatedMediaModel; + } + + public DirectItemType getItemType() { + return itemType; + } + + public CharSequence getText() { + return text; + } + + public String getItemId() { + return itemId; + } + + public long getUserId() { + return userId; + } + + public long getTimestamp() { + return timestamp; + } + + @NonNull + public String getDateTime() { + return Utils.datetimeParser.format(new Date(timestamp / 1000L)); + } + + public ProfileModel getProfileModel() { + return profileModel; + } + + public DirectItemLinkModel getLinkModel() { + return linkModel; + } + + public DirectItemMediaModel getMediaModel() { + return mediaModel; + } + + public DirectItemReelShareModel getReelShare() { + return reelShare; + } + + public DirectItemActionLogModel getActionLogModel() { + return actionLogModel; + } + + public DirectItemVoiceMediaModel getVoiceMediaModel() { + return voiceMediaModel; + } + + public DirectItemRavenMediaModel getRavenMediaModel() { + return ravenMediaModel; + } + + public DirectItemAnimatedMediaModel getAnimatedMediaModel() { + return animatedMediaModel; + } + + public DirectItemVideoCallEventModel getVideoCallEventModel() { + return videoCallEventModel; + } + + @Override + public int compareTo(@NonNull final DirectItemModel o) { + return Long.compare(timestamp, o.timestamp); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + public final static class DirectItemAnimatedMediaModel implements Serializable { + private final boolean isRandom, isSticker; + private final String id; + private final String gifUrl, webpUrl, mp4Url; + private final int height, width; + + public DirectItemAnimatedMediaModel(final boolean isRandom, final boolean isSticker, final String id, final String gifUrl, + final String webpUrl, final String mp4Url, final int height, final int width) { + this.isRandom = isRandom; + this.isSticker = isSticker; + this.id = id; + this.gifUrl = gifUrl; + this.webpUrl = webpUrl; + this.mp4Url = mp4Url; + this.height = height; + this.width = width; + } + + public boolean isRandom() { + return isRandom; + } + + public boolean isSticker() { + return isSticker; + } + + public String getId() { + return id; + } + + public String getGifUrl() { + return gifUrl; + } + + public String getWebpUrl() { + return webpUrl; + } + + public String getMp4Url() { + return mp4Url; + } + + public int getHeight() { + return height; + } + + public int getWidth() { + return width; + } + } + + public final static class DirectItemVoiceMediaModel implements Serializable { + private final String id, audioUrl; + private final long durationMs; + private final int[] waveformData; + private int progress; + private boolean isPlaying = false; + + public DirectItemVoiceMediaModel(final String id, final String audioUrl, final long durationMs, final int[] waveformData) { + this.id = id; + this.audioUrl = audioUrl; + this.durationMs = durationMs; + this.waveformData = waveformData; + } + + public String getId() { + return id; + } + + public String getAudioUrl() { + return audioUrl; + } + + public long getDurationMs() { + return durationMs; + } + + public int[] getWaveformData() { + return waveformData; + } + + public void setProgress(final int progress) { + this.progress = progress; + } + + public int getProgress() { + return progress; + } + + public boolean isPlaying() { + return isPlaying; + } + + public void setPlaying(final boolean playing) { + isPlaying = playing; + } + } + + public final static class DirectItemLinkModel implements Serializable { + private final String text; + private final String clientContext; + private final String mutationToken; + private final DirectItemLinkContext linkContext; + + public DirectItemLinkModel(final String text, final String clientContext, final String mutationToken, + final DirectItemLinkContext linkContext) { + this.text = text; + this.clientContext = clientContext; + this.mutationToken = mutationToken; + this.linkContext = linkContext; + } + + public String getText() { + return text; + } + + public String getClientContext() { + return clientContext; + } + + public String getMutationToken() { + return mutationToken; + } + + public DirectItemLinkContext getLinkContext() { + return linkContext; + } + } + + public final static class DirectItemLinkContext implements Serializable { + private final String linkUrl; + private final String linkTitle; + private final String linkSummary; + private final String linkImageUrl; + + public DirectItemLinkContext(final String linkUrl, final String linkTitle, final String linkSummary, final String linkImageUrl) { + this.linkUrl = linkUrl; + this.linkTitle = linkTitle; + this.linkSummary = linkSummary; + this.linkImageUrl = linkImageUrl; + } + + public String getLinkUrl() { + return linkUrl; + } + + public String getLinkTitle() { + return linkTitle; + } + + public String getLinkSummary() { + return linkSummary; + } + + public String getLinkImageUrl() { + return linkImageUrl; + } + } + + public final static class DirectItemActionLogModel implements Serializable { + private final String description; + + public DirectItemActionLogModel(final String description) { + this.description = description; + } + + public String getDescription() { + return description; + } + } + + public final static class DirectItemReelShareModel implements Serializable { + private final boolean isReelPersisted; + private final long reelOwnerId; + private final String text; + private final String type; + private final String reelType; + private final String reelName; + private final String reelId; + private final DirectItemMediaModel media; + + public DirectItemReelShareModel(final boolean isReelPersisted, final long reelOwnerId, final String text, final String type, + final String reelType, final String reelName, final String reelId, final DirectItemMediaModel media) { + this.isReelPersisted = isReelPersisted; + this.reelOwnerId = reelOwnerId; + this.text = text; + this.type = type; + this.reelType = reelType; + this.reelName = reelName; + this.reelId = reelId; + this.media = media; + } + + public boolean isReelPersisted() { + return isReelPersisted; + } + + public long getReelOwnerId() { + return reelOwnerId; + } + + public String getText() { + return text; + } + + public String getType() { + return type; + } + + public String getReelType() { + return reelType; + } + + public String getReelName() { + return reelName; + } + + public String getReelId() { + return reelId; + } + + public DirectItemMediaModel getMedia() { + return media; + } + } + + public final static class DirectItemMediaModel implements Serializable { + private final MediaItemType mediaType; + private final long expiringAt, pk; + private final String id, thumbUrl; + private final ProfileModel user; + + public DirectItemMediaModel(final MediaItemType mediaType, final long expiringAt, final long pk, final String id, + final String thumbUrl, final ProfileModel user) { + this.mediaType = mediaType; + this.expiringAt = expiringAt; + this.pk = pk; + this.id = id; + this.thumbUrl = thumbUrl; + this.user = user; + } + + public MediaItemType getMediaType() { + return mediaType; + } + + public long getExpiringAt() { + return expiringAt; + } + + public long getPk() { + return pk; + } + + public String getId() { + return id; + } + + public ProfileModel getUser() { + return user; + } + + public String getThumbUrl() { + return thumbUrl; + } + } + + public final static class DirectItemRavenMediaModel implements Serializable { + private final long expireAtSecs; + private final int playbackDurationSecs; + private final int seenCount; + private final String[] seenUserIds; + private final RavenMediaViewType viewType; + private final DirectItemMediaModel media; + private final RavenExpiringMediaActionSummaryModel expiringMediaActionSummary; + + public DirectItemRavenMediaModel(final long expireAtSecs, final int playbackDurationSecs, final int seenCount, + final String[] seenUserIds, final RavenMediaViewType viewType, final DirectItemMediaModel media, + final RavenExpiringMediaActionSummaryModel expiringMediaActionSummary) { + this.expireAtSecs = expireAtSecs; + this.playbackDurationSecs = playbackDurationSecs; + this.seenCount = seenCount; + this.seenUserIds = seenUserIds; + this.viewType = viewType; + this.media = media; + this.expiringMediaActionSummary = expiringMediaActionSummary; + } + + public long getExpireAtSecs() { + return expireAtSecs; + } + + public int getPlaybackDurationSecs() { + return playbackDurationSecs; + } + + public int getSeenCount() { + return seenCount; + } + + public String[] getSeenUserIds() { + return seenUserIds; + } + + public RavenMediaViewType getViewType() { + return viewType; + } + + public DirectItemMediaModel getMedia() { + return media; + } + + public RavenExpiringMediaActionSummaryModel getExpiringMediaActionSummary() { + return expiringMediaActionSummary; + } + } + + public final static class DirectItemVideoCallEventModel implements Serializable { + private final long videoCallId; + private final boolean hasAudioOnlyCall; + private final String action; + private final String description; + + public DirectItemVideoCallEventModel(final long videoCallId, final boolean hasAudioOnlyCall, final String action, final String description) { + this.videoCallId = videoCallId; + this.hasAudioOnlyCall = hasAudioOnlyCall; + this.action = action; + this.description = description; + } + + public long getVideoCallId() { + return videoCallId; + } + + public boolean isHasAudioOnlyCall() { + return hasAudioOnlyCall; + } + + public String getAction() { + return action; + } + + public String getDescription() { + return description; + } + } + + public final static class RavenExpiringMediaActionSummaryModel implements Serializable { + private final long timestamp; + private final int count; + private final RavenExpiringMediaType type; + + public RavenExpiringMediaActionSummaryModel(final long timestamp, final int count, final RavenExpiringMediaType type) { + this.timestamp = timestamp; + this.count = count; + this.type = type; + } + + public long getTimestamp() { + return timestamp; + } + + public int getCount() { + return count; + } + + public RavenExpiringMediaType getType() { + return type; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/direct_messages/InboxMediaModel.java b/app/src/main/java/awais/instagrabber/models/direct_messages/InboxMediaModel.java new file mode 100755 index 00000000..e4746c41 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/direct_messages/InboxMediaModel.java @@ -0,0 +1,27 @@ +package awais.instagrabber.models.direct_messages; + +import awais.instagrabber.models.enums.MediaItemType; + +public final class InboxMediaModel { + private final MediaItemType mediaType; + private final String mediaId; + private final String displayUrl; + + public InboxMediaModel(final MediaItemType mediaType, final String mediaId, final String displayUrl) { + this.mediaType = mediaType; + this.mediaId = mediaId; + this.displayUrl = displayUrl; + } + + public MediaItemType getMediaType() { + return mediaType; + } + + public String getMediaId() { + return mediaId; + } + + public String getDisplayUrl() { + return displayUrl; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/direct_messages/InboxModel.java b/app/src/main/java/awais/instagrabber/models/direct_messages/InboxModel.java new file mode 100755 index 00000000..48be23f0 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/direct_messages/InboxModel.java @@ -0,0 +1,63 @@ +package awais.instagrabber.models.direct_messages; + +public final class InboxModel { + private final boolean hasOlder, hasPendingTopRequests, blendedInboxEnabled; + private final int unseenCount, pendingRequestsCount; + private final long seqId, unseenCountTimestamp; + private final InboxThreadModel[] threads; + private String oldestCursor; + + public InboxModel(final boolean hasOlder, final boolean hasPendingTopRequests, final boolean blendedInboxEnabled, + final int unseenCount, final int pendingRequestsCount, final long seqId, final long unseenCountTimestamp, + final String oldestCursor, final InboxThreadModel[] threads) { + this.hasOlder = hasOlder; + this.hasPendingTopRequests = hasPendingTopRequests; + this.blendedInboxEnabled = blendedInboxEnabled; + this.unseenCount = unseenCount; + this.pendingRequestsCount = pendingRequestsCount; + this.unseenCountTimestamp = unseenCountTimestamp; + this.oldestCursor = oldestCursor; + this.threads = threads; + this.seqId = seqId; + } + + public boolean isHasOlder() { + return hasOlder; + } + + public boolean isHasPendingTopRequests() { + return hasPendingTopRequests; + } + + public boolean isBlendedInboxEnabled() { + return blendedInboxEnabled; + } + + public int getUnseenCount() { + return unseenCount; + } + + public int getPendingRequestsCount() { + return pendingRequestsCount; + } + + public long getUnseenCountTimestamp() { + return unseenCountTimestamp; + } + + public long getSeqId() { + return seqId; + } + + public String getOldestCursor() { + return oldestCursor; + } + + public void setOldestCursor(final String oldestCursor) { + this.oldestCursor = oldestCursor; + } + + public InboxThreadModel[] getThreads() { + return threads; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/direct_messages/InboxThreadModel.java b/app/src/main/java/awais/instagrabber/models/direct_messages/InboxThreadModel.java new file mode 100755 index 00000000..9678023a --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/direct_messages/InboxThreadModel.java @@ -0,0 +1,145 @@ +package awais.instagrabber.models.direct_messages; + +import java.io.Serializable; + +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.models.enums.InboxReadState; + +public final class InboxThreadModel implements Serializable { + private final InboxReadState readState; + private final String threadId, threadV2Id, threadType, threadTitle, newestCursor, oldestCursor, nextCursor, prevCursor; + private final ProfileModel inviter; + private final ProfileModel[] users, leftUsers; + private final DirectItemModel[] items; + private final boolean muted, isPin, isSpam, isGroup, named, pending, archived, canonical, hasOlder, hasNewer; + private final long lastActivityAt; + + public InboxThreadModel(final InboxReadState readState, final String threadId, final String threadV2Id, final String threadType, final String threadTitle, + final String newestCursor, final String oldestCursor, final String nextCursor, final String prevCursor, + final ProfileModel inviter, final ProfileModel[] users, + final ProfileModel[] leftUsers, final DirectItemModel[] items, final boolean muted, + final boolean isPin, final boolean named, final boolean canonical, final boolean pending, + final boolean hasOlder, final boolean hasNewer, final boolean isSpam, final boolean isGroup, + final boolean archived, final long lastActivityAt) { + this.readState = readState; + this.threadId = threadId; + this.threadV2Id = threadV2Id; + this.threadType = threadType; + this.threadTitle = threadTitle; + this.newestCursor = newestCursor; + this.oldestCursor = oldestCursor; + this.nextCursor = nextCursor; + this.prevCursor = prevCursor; + this.inviter = inviter; + this.users = users; + this.leftUsers = leftUsers; + this.items = items; // todo + this.muted = muted; + this.isPin = isPin; + this.named = named; + this.canonical = canonical; + this.pending = pending; + this.hasOlder = hasOlder; + this.hasNewer = hasNewer; + this.isSpam = isSpam; + this.isGroup = isGroup; + this.archived = archived; + this.lastActivityAt = lastActivityAt; + } + + public InboxReadState getReadState() { + return readState; + } + + public String getThreadId() { + return threadId; + } + + public String getThreadV2Id() { + return threadV2Id; + } + + public String getThreadType() { + return threadType; + } + + public String getThreadTitle() { + return threadTitle; + } + + public String getNewestCursor() { + return newestCursor; + } + + public String getOldestCursor() { + return oldestCursor; + } + + public String getNextCursor() { + return nextCursor; + } + + public String getPrevCursor() { + return prevCursor; + } + + public ProfileModel getInviter() { + return inviter; + } + + public ProfileModel[] getUsers() { + return users; + } + + public ProfileModel[] getLeftUsers() { + return leftUsers; + } + + public DirectItemModel[] getItems() { + return items; + } + + public boolean isMuted() { + return muted; + } + + public boolean isPin() { + return isPin; + } + + public boolean isNamed() { + return named; + } + + public boolean isPending() { + return pending; + } + + public boolean isArchived() { + return archived; + } + + public boolean isCanonical() { + return canonical; + } + + public boolean isHasOlder() { + return hasOlder; + } + + public boolean isHasNewer() { + return hasNewer; + } + + public boolean isSpam() { + return isSpam; + } + + public boolean isGroup() { + return isGroup; + } + + public long getLastActivityAt() { + return lastActivityAt; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/enums/DirectItemType.java b/app/src/main/java/awais/instagrabber/models/enums/DirectItemType.java new file mode 100755 index 00000000..ee34f7f2 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/enums/DirectItemType.java @@ -0,0 +1,19 @@ +package awais.instagrabber.models.enums; + +import java.io.Serializable; + +public enum DirectItemType implements Serializable { + TEXT, + LIKE, + LINK, + MEDIA, + RAVEN_MEDIA, + PROFILE, + VIDEO_CALL_EVENT, + ANIMATED_MEDIA, + VOICE_MEDIA, + MEDIA_SHARE, + REEL_SHARE, + ACTION_LOG, + PLACEHOLDER, +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/enums/DownloadMethod.java b/app/src/main/java/awais/instagrabber/models/enums/DownloadMethod.java new file mode 100755 index 00000000..9c3c9595 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/enums/DownloadMethod.java @@ -0,0 +1,9 @@ +package awais.instagrabber.models.enums; + +public enum DownloadMethod { + DOWNLOAD_MAIN, + DOWNLOAD_DISCOVER, + DOWNLOAD_FEED, + DOWNLOAD_POST_VIEWER, + DOWNLOAD_DIRECT; +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/enums/InboxReadState.java b/app/src/main/java/awais/instagrabber/models/enums/InboxReadState.java new file mode 100755 index 00000000..0924b435 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/enums/InboxReadState.java @@ -0,0 +1,8 @@ +package awais.instagrabber.models.enums; + +import java.io.Serializable; + +public enum InboxReadState implements Serializable { + STATE_READ, + STATE_UNREAD, +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/enums/IntentModelType.java b/app/src/main/java/awais/instagrabber/models/enums/IntentModelType.java new file mode 100755 index 00000000..5d17b167 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/enums/IntentModelType.java @@ -0,0 +1,8 @@ +package awais.instagrabber.models.enums; + +public enum IntentModelType { + UNKNOWN, + USERNAME, + POST, + HASHTAG, +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/enums/ItemGetType.java b/app/src/main/java/awais/instagrabber/models/enums/ItemGetType.java new file mode 100755 index 00000000..b6e7055b --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/enums/ItemGetType.java @@ -0,0 +1,9 @@ +package awais.instagrabber.models.enums; + +import java.io.Serializable; + +public enum ItemGetType implements Serializable { + MAIN_ITEMS, + DISCOVER_ITEMS, + FEED_ITEMS, +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/enums/MediaItemType.java b/app/src/main/java/awais/instagrabber/models/enums/MediaItemType.java new file mode 100755 index 00000000..97433550 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/enums/MediaItemType.java @@ -0,0 +1,10 @@ +package awais.instagrabber.models.enums; + +import java.io.Serializable; + +public enum MediaItemType implements Serializable { + MEDIA_TYPE_IMAGE, + MEDIA_TYPE_VIDEO, + MEDIA_TYPE_SLIDER, + MEDIA_TYPE_VOICE, +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/enums/ProfilePictureFetchMode.java b/app/src/main/java/awais/instagrabber/models/enums/ProfilePictureFetchMode.java new file mode 100755 index 00000000..d60f590e --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/enums/ProfilePictureFetchMode.java @@ -0,0 +1,7 @@ +package awais.instagrabber.models.enums; + +public enum ProfilePictureFetchMode { + INSTADP, + INSTA_STALKER, + INSTAFULLSIZE, +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/enums/RavenExpiringMediaType.java b/app/src/main/java/awais/instagrabber/models/enums/RavenExpiringMediaType.java new file mode 100755 index 00000000..889a5ccf --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/enums/RavenExpiringMediaType.java @@ -0,0 +1,15 @@ +package awais.instagrabber.models.enums; + +// thanks to http://github.com/warifp/InstagramAutoPostImageUrl/blob/master/vendor/mgp25/instagram-php/src/Response/Model/ActionBadge.php +public enum RavenExpiringMediaType { + RAVEN_DELIVERED, + RAVEN_SENT, + RAVEN_OPENED, + RAVEN_SCREENSHOT, + RAVEN_REPLAYED, + RAVEN_CANNOT_DELIVER, + RAVEN_SENDING, + RAVEN_BLOCKED, + RAVEN_UNKNOWN, + RAVEN_SUGGESTED, +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/enums/RavenMediaViewType.java b/app/src/main/java/awais/instagrabber/models/enums/RavenMediaViewType.java new file mode 100755 index 00000000..4e45649c --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/enums/RavenMediaViewType.java @@ -0,0 +1,7 @@ +package awais.instagrabber.models.enums; + +public enum RavenMediaViewType { + PERMANENT, + REPLAYABLE, + ONCE, +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/enums/SuggestionType.java b/app/src/main/java/awais/instagrabber/models/enums/SuggestionType.java new file mode 100755 index 00000000..917e1e60 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/enums/SuggestionType.java @@ -0,0 +1,6 @@ +package awais.instagrabber.models.enums; + +public enum SuggestionType { + TYPE_USER, + TYPE_HASHTAG, +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/enums/UserInboxDirection.java b/app/src/main/java/awais/instagrabber/models/enums/UserInboxDirection.java new file mode 100755 index 00000000..620c50f0 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/enums/UserInboxDirection.java @@ -0,0 +1,6 @@ +package awais.instagrabber.models.enums; + +public enum UserInboxDirection { + OLDER, + NEWER, +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/ChangelogFetcher.java b/app/src/main/java/awais/instagrabber/utils/ChangelogFetcher.java new file mode 100755 index 00000000..b1e0740f --- /dev/null +++ b/app/src/main/java/awais/instagrabber/utils/ChangelogFetcher.java @@ -0,0 +1,50 @@ +package awais.instagrabber.utils; + +import android.os.AsyncTask; +import android.util.Log; + +import java.net.HttpURLConnection; +import java.net.URL; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; + +public final class ChangelogFetcher extends AsyncTask { + private final FetchListener fetchListener; + + public ChangelogFetcher(final FetchListener fetchListener) { + this.fetchListener = fetchListener; + } + + @Override + protected String doInBackground(final Void... voids) { + String result = null; + final String changelogUrl = "https://gitlab.com/AwaisKing/instagrabber/-/raw/master/CHANGELOG"; + + try { + final HttpURLConnection conn = (HttpURLConnection) new URL(changelogUrl).openConnection(); + conn.setUseCaches(false); + conn.connect(); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + result = Utils.readFromConnection(conn); + } + + conn.disconnect(); + } catch (final Exception e) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return result; + } + + @Override + protected void onPreExecute() { + if (fetchListener != null) fetchListener.doBefore(); + } + + @Override + protected void onPostExecute(final String result) { + if (fetchListener != null) fetchListener.onResult(result); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/Constants.java b/app/src/main/java/awais/instagrabber/utils/Constants.java new file mode 100755 index 00000000..3286aed2 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/utils/Constants.java @@ -0,0 +1,45 @@ +package awais.instagrabber.utils; + +public final class Constants { + // string prefs + public static final String FOLDER_PATH = "custom_path"; + public static final String DATE_TIME_FORMAT = "date_time_format"; + public static final String DATE_TIME_SELECTION = "date_time_selection"; + public static final String CUSTOM_DATE_TIME_FORMAT = "date_time_custom_format"; + // int prefs + public static final String APP_THEME = "app_theme"; + public static final String APP_LANGUAGE = "app_language"; + public static final String PREV_INSTALL_VERSION = "prevVersion"; + public static final String PROFILE_FETCH_MODE = "profile_fetch_mode"; + // boolean prefs + public static final String DOWNLOAD_USER_FOLDER = "download_user_folder"; + public static final String BOTTOM_TOOLBAR = "bottom_toolbar"; + public static final String FOLDER_SAVE_TO = "saved_to"; + public static final String AUTOPLAY_VIDEOS = "autoplay_videos"; + public static final String MUTED_VIDEOS = "muted_videos"; + public static final String AUTOLOAD_POSTS = "autoload_posts"; + public static final String SHOW_FEED = "show_feed"; + public static final String CUSTOM_DATE_TIME_FORMAT_ENABLED = "data_time_custom_enabled"; + // never Export + public static final String COOKIE = "cookie"; + public static final String SHOW_QUICK_ACCESS_DIALOG = "show_quick_dlg"; + //////////////////////// EXTRAS //////////////////////// + public static final String EXTRAS_USER = "user"; + public static final String EXTRAS_USERNAME = "username"; + public static final String EXTRAS_ID = "id"; + public static final String EXTRAS_POST = "post"; + public static final String EXTRAS_PROFILE = "profile"; + public static final String EXTRAS_TYPE = "type"; + public static final String EXTRAS_NAME = "name"; + public static final String EXTRAS_STORIES = "stories"; + public static final String EXTRAS_HIGHLIGHT = "highlight"; + public static final String EXTRAS_INDEX = "index"; + public static final String EXTRAS_THREAD_MODEL = "threadModel"; + public static final String EXTRAS_FOLLOWERS = "followers"; + public static final String EXTRAS_SHORTCODE = "shortcode"; + public static final String EXTRAS_END_CURSOR = "endCursor"; + //////////////////////// EXTRAS //////////////////////// + public static final String USER_AGENT = "Mozilla/5.0 (Linux; Android 8.1.0; motorola one Build/OPKS28.63-18-3; wv) " + + "AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36 " + + "Instagram 72.0.0.21.98 Android (27/8.1.0; 320dpi; 720x1362; motorola; motorola one; deen_sprout; qcom; pt_BR; 132081645)"; +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/DataBox.java b/app/src/main/java/awais/instagrabber/utils/DataBox.java new file mode 100755 index 00000000..1189bdd0 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/utils/DataBox.java @@ -0,0 +1,271 @@ +package awais.instagrabber.utils; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.ArrayList; + +import awais.instagrabber.BuildConfig; +import awaisomereport.LogCollector; + +import static awais.instagrabber.utils.Utils.logCollector; + +public final class DataBox extends SQLiteOpenHelper { + private static DataBox sInstance; + private final static int VERSION = 1; + private final static String TABLE_COOKIES = "cookies"; + private final static String TABLE_FAVORITES = "favorites"; + private final static String KEY_DATE_ADDED = "date_added"; + private final static String KEY_QUERY_TEXT = "query_text"; + private final static String KEY_USERNAME = Constants.EXTRAS_USERNAME; + private final static String KEY_COOKIE = "cookie"; + private final static String KEY_UID = "uid"; + + public static synchronized DataBox getInstance(final Context context) { + if (sInstance == null) sInstance = new DataBox(context.getApplicationContext()); + return sInstance; + } + + public DataBox(@Nullable final Context context) { + super(context, "cookiebox.db", null, VERSION); + } + + @Override + public void onCreate(@NonNull final SQLiteDatabase db) { + db.execSQL("CREATE TABLE cookies (id INTEGER PRIMARY KEY, uid TEXT, username TEXT, cookie TEXT)"); + db.execSQL("CREATE TABLE favorites (id INTEGER PRIMARY KEY, query_text TEXT, date_added INTEGER)"); + } + + @Override + public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { } + + ///////////////////////////////////////// YOUR WEIRD FETIS-FAVORITES! HERE ///////////////////////////////////////// + public final void addFavorite(@NonNull final FavoriteModel favoriteModel) { + final String query = favoriteModel.getQuery(); + if (!Utils.isEmpty(query)) { + try (final SQLiteDatabase db = getWritableDatabase()) { + db.beginTransaction(); + try { + final ContentValues values = new ContentValues(); + values.put(KEY_DATE_ADDED, favoriteModel.getDate()); + values.put(KEY_QUERY_TEXT, query); + + final int rows = db.update(TABLE_FAVORITES, values, KEY_QUERY_TEXT + "=?", new String[]{query}); + + if (rows != 1) + db.insertOrThrow(TABLE_FAVORITES, null, values); + + db.setTransactionSuccessful(); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.DATA_BOX_FAVORITES, "addFavorite"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } finally { + db.endTransaction(); + } + } + } + } + + public final synchronized void delFavorite(@NonNull final FavoriteModel favoriteModel) { + final String query = favoriteModel.getQuery(); + if (!Utils.isEmpty(query)) { + try (final SQLiteDatabase db = getWritableDatabase()) { + db.beginTransaction(); + try { + final int rowsDeleted = db.delete(TABLE_FAVORITES, KEY_QUERY_TEXT + "=? AND " + KEY_DATE_ADDED + "=?", + new String[]{query, Long.toString(favoriteModel.getDate())}); + + if (rowsDeleted > 0) db.setTransactionSuccessful(); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.DATA_BOX_FAVORITES, "delFavorite"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } finally { + db.endTransaction(); + } + } + } + } + + @Nullable + public final ArrayList getAllFavorites() { + ArrayList favorites = null; + + try (final SQLiteDatabase db = getReadableDatabase(); + final Cursor cursor = db.rawQuery("SELECT query_text, date_added FROM favorites ORDER BY date_added DESC", null)) { + if (cursor != null && cursor.moveToFirst()) { + favorites = new ArrayList<>(); + do { + favorites.add(new FavoriteModel( + cursor.getString(0), // query text + cursor.getLong(1) // date added + )); + } while (cursor.moveToNext()); + } + } + + return favorites; + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + ///////////////////////////////////// YOUR COOKIES FOR COOKIE MONSTER ARE HERE ///////////////////////////////////// + public final void addUserCookie(@NonNull final CookieModel cookieModel) { + final String cookieModelUid = cookieModel.getUid(); + if (!Utils.isEmpty(cookieModelUid)) { + try (final SQLiteDatabase db = getWritableDatabase()) { + db.beginTransaction(); + try { + final ContentValues values = new ContentValues(); + values.put(KEY_USERNAME, cookieModel.getUsername()); + values.put(KEY_COOKIE, cookieModel.getCookie()); + values.put(KEY_UID, cookieModelUid); + + final int rows = db.update(TABLE_COOKIES, values, KEY_UID + "=?", new String[]{cookieModelUid}); + + if (rows != 1) + db.insertOrThrow(TABLE_COOKIES, null, values); + + db.setTransactionSuccessful(); + } catch (final Exception e) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } finally { + db.endTransaction(); + } + } + } + } + + public final synchronized void delUserCookie(@NonNull final CookieModel cookieModel) { + final String cookieModelUid = cookieModel.getUid(); + if (!Utils.isEmpty(cookieModelUid)) { + try (final SQLiteDatabase db = getWritableDatabase()) { + db.beginTransaction(); + try { + final int rowsDeleted = db.delete(TABLE_COOKIES, KEY_UID + "=? AND " + KEY_USERNAME + "=? AND " + KEY_COOKIE + "=?", + new String[]{cookieModelUid, cookieModel.getUsername(), cookieModel.getCookie()}); + + if (rowsDeleted > 0) db.setTransactionSuccessful(); + } catch (final Exception e) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } finally { + db.endTransaction(); + } + } + } + } + + public final int getCookieCount() { + int cookieCount = 0; + try (final SQLiteDatabase db = getReadableDatabase(); + final Cursor cursor = db.rawQuery("SELECT * FROM cookies", null)) { + if (cursor != null) cookieCount = cursor.getCount(); + } + return cookieCount; + } + + @Nullable + public final CookieModel getCookie(final String uid) { + CookieModel cookie = null; + try (final SQLiteDatabase db = getReadableDatabase(); + final Cursor cursor = db.rawQuery("SELECT uid, username, cookie FROM cookies WHERE uid = ?", new String[]{uid})) { + if (cursor != null && cursor.moveToFirst()) + cookie = new CookieModel( + cursor.getString(0), // uid + cursor.getString(1), // username + cursor.getString(2) // cookie + ); + } + return cookie; + } + + @Nullable + public final ArrayList getAllCookies() { + ArrayList cookies = null; + + try (final SQLiteDatabase db = getReadableDatabase(); + final Cursor cursor = db.rawQuery("SELECT uid, username, cookie FROM cookies", null)) { + if (cursor != null && cursor.moveToFirst()) { + cookies = new ArrayList<>(); + do { + cookies.add(new CookieModel( + cursor.getString(0), // uid + cursor.getString(1), // username + cursor.getString(2) // cookie + )); + } while (cursor.moveToNext()); + } + } + + return cookies; + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + public static class CookieModel { + private final String uid, username, cookie; + private boolean selected; + + public CookieModel(final String uid, final String username, final String cookie) { + this.uid = uid; + this.username = username; + this.cookie = cookie; + } + + public String getUid() { + return uid; + } + + public String getUsername() { + return username; + } + + public String getCookie() { + return cookie; + } + + public boolean isSelected() { + return selected; + } + + public void setSelected(final boolean selected) { + this.selected = selected; + } + + @NonNull + @Override + public String toString() { + return username; + } + } + + public static class FavoriteModel { + private final String query; + private final long date; + + public FavoriteModel(final String query, final long date) { + this.query = query; + this.date = date; + } + + public String getQuery() { + return query; + } + + public long getDate() { + return date; + } + + @NonNull + @Override + public String toString() { + return query; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/DirectoryChooser.java b/app/src/main/java/awais/instagrabber/utils/DirectoryChooser.java new file mode 100755 index 00000000..9c912272 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/utils/DirectoryChooser.java @@ -0,0 +1,248 @@ +package awais.instagrabber.utils; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.os.Environment; +import android.os.FileObserver; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import awais.instagrabber.R; +import awais.instagrabber.adapters.SimpleAdapter; + +public final class DirectoryChooser extends DialogFragment { + public static final String KEY_CURRENT_DIRECTORY = "CURRENT_DIRECTORY"; + private static final File sdcardPathFile = Environment.getExternalStorageDirectory(); + private static final String sdcardPath = sdcardPathFile.getPath(); + private final List fileNames = new ArrayList<>(); + private Context context; + private View btnConfirm, btnNavUp, btnCancel; + private File selectedDir; + private String initialDirectory; + private TextView tvSelectedFolder; + private FileObserver fileObserver; + private SimpleAdapter listDirectoriesAdapter; + private OnFragmentInteractionListener interactionListener; + private boolean showZaAiConfigFiles = false; + + public DirectoryChooser() { + super(); + } + + public DirectoryChooser setInitialDirectory(final String initialDirectory) { + if (!Utils.isEmpty(initialDirectory)) + this.initialDirectory = initialDirectory; + return this; + } + + public DirectoryChooser setShowZaAiConfigFiles(final boolean showZaAiConfigFiles) { + this.showZaAiConfigFiles = showZaAiConfigFiles; + return this; + } + + @Override + public void onAttach(@NonNull final Context context) { + super.onAttach(context); + + this.context = context; + + if (this.context instanceof OnFragmentInteractionListener) + interactionListener = (OnFragmentInteractionListener) this.context; + else { + final Fragment owner = getTargetFragment(); + if (owner instanceof OnFragmentInteractionListener) + interactionListener = (OnFragmentInteractionListener) owner; + } + } + + @NonNull + @Override + public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) { + Context context = this.context; + if (context == null) context = getContext(); + if (context == null) context = getActivity(); + if (context == null) context = inflater.getContext(); + + final View view = inflater.inflate(R.layout.layout_directory_chooser, container, false); + + btnNavUp = view.findViewById(R.id.btnNavUp); + btnCancel = view.findViewById(R.id.btnCancel); + btnConfirm = view.findViewById(R.id.btnConfirm); + tvSelectedFolder = view.findViewById(R.id.txtvSelectedFolder); + + final View.OnClickListener clickListener = v -> { + final Object tag; + if (v instanceof TextView && (tag = v.getTag()) instanceof CharSequence) { + final File file = new File(selectedDir, tag.toString()); + if (file.isDirectory()) + changeDirectory(file); + else if (showZaAiConfigFiles && file.isFile()) { + if (interactionListener != null && file.canRead()) + interactionListener.onSelectDirectory(file.getAbsolutePath()); + dismiss(); + } + + } else if (v == btnNavUp) { + final File parent; + if (selectedDir != null && (parent = selectedDir.getParentFile()) != null) + changeDirectory(parent); + + } else if (v == btnConfirm) { + if (interactionListener != null && isValidFile(selectedDir)) + interactionListener.onSelectDirectory(selectedDir.getAbsolutePath()); + dismiss(); + } else if (v == btnCancel) { + dismiss(); + } + }; + + btnNavUp.setOnClickListener(clickListener); + btnCancel.setOnClickListener(clickListener); + btnConfirm.setOnClickListener(clickListener); + + listDirectoriesAdapter = new SimpleAdapter<>(context, fileNames, clickListener); + + final RecyclerView directoriesList = view.findViewById(R.id.directoryList); + directoriesList.setLayoutManager(new LinearLayoutManager(context)); + directoriesList.setAdapter(listDirectoriesAdapter); + + final File initDir = new File(initialDirectory); + final File initialDir = !Utils.isEmpty(initialDirectory) && isValidFile(initDir) ? initDir : Environment.getExternalStorageDirectory(); + + changeDirectory(initialDir); + + return view; + } + + @Override + public void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if (Utils.isEmpty(initialDirectory)) { + initialDirectory = new File(sdcardPath, "Download").getAbsolutePath(); + if (savedInstanceState != null) { + final String savedDir = savedInstanceState.getString(KEY_CURRENT_DIRECTORY); + if (!Utils.isEmpty(savedDir)) initialDirectory = savedDir; + } + } + + setStyle(DialogFragment.STYLE_NO_TITLE, 0); + } + + @NonNull + @Override + public Dialog onCreateDialog(final Bundle savedInstanceState) { + return new Dialog(context, R.attr.alertDialogTheme) { + @Override + public void onBackPressed() { + if (selectedDir != null) { + final String absolutePath = selectedDir.getAbsolutePath(); + if (absolutePath.equals(sdcardPath) || absolutePath.equals(sdcardPathFile.getAbsolutePath())) + dismiss(); + else + changeDirectory(selectedDir.getParentFile()); + } + } + }; + } + + @Override + public void onSaveInstanceState(@NonNull final Bundle outState) { + super.onSaveInstanceState(outState); + if (selectedDir != null) outState.putString(KEY_CURRENT_DIRECTORY, selectedDir.getAbsolutePath()); + } + + @Override + public void onResume() { + super.onResume(); + if (fileObserver != null) fileObserver.startWatching(); + } + + @Override + public void onPause() { + super.onPause(); + if (fileObserver != null) fileObserver.stopWatching(); + } + + @Override + public void onDetach() { + super.onDetach(); + interactionListener = null; + } + + private void changeDirectory(final File dir) { + if (dir != null && dir.isDirectory()) { + final String path = dir.getAbsolutePath(); + + final File[] contents = dir.listFiles(); + if (contents != null) { + fileNames.clear(); + + for (final File f : contents) { + final String name = f.getName(); + if (f.isDirectory() || showZaAiConfigFiles && f.isFile() && name.toLowerCase().endsWith(".zaai")) + fileNames.add(name); + } + + Collections.sort(fileNames); + selectedDir = dir; + tvSelectedFolder.setText(path); + listDirectoriesAdapter.notifyDataSetChanged(); + fileObserver = new FileObserver(path, FileObserver.CREATE | FileObserver.DELETE | FileObserver.MOVED_FROM | FileObserver.MOVED_TO) { + private final Runnable currentDirRefresher = () -> changeDirectory(selectedDir); + + @Override + public void onEvent(final int event, final String path) { + if (context instanceof Activity) ((Activity) context).runOnUiThread(currentDirRefresher); + } + }; + fileObserver.startWatching(); + } + } + refreshButtonState(); + } + + private void refreshButtonState() { + if (selectedDir != null) { + final String path = selectedDir.getAbsolutePath(); + toggleUpButton(!path.equals(sdcardPathFile.getAbsolutePath()) && selectedDir != sdcardPathFile); + btnConfirm.setEnabled(isValidFile(selectedDir)); + } + } + + private void toggleUpButton(final boolean enable) { + if (btnNavUp != null) { + btnNavUp.setEnabled(enable); + btnNavUp.setAlpha(enable ? 1f : 0.617f); + } + } + + private boolean isValidFile(final File file) { + return file != null && file.isDirectory() && file.canRead(); + } + + public DirectoryChooser setInteractionListener(final OnFragmentInteractionListener interactionListener) { + this.interactionListener = interactionListener; + return this; + } + + public interface OnFragmentInteractionListener { + void onSelectDirectory(final String path); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java b/app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java new file mode 100755 index 00000000..25f0b6a3 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java @@ -0,0 +1,328 @@ +package awais.instagrabber.utils; + +import android.content.Context; +import android.text.InputFilter; +import android.text.InputType; +import android.util.Base64; +import android.util.Log; +import android.widget.Toast; + +import androidx.annotation.IntDef; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.AppCompatEditText; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.Iterator; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.R; +import awais.instagrabber.interfaces.FetchListener; +import awaisomereport.LogCollector.LogFile; + +import static awais.instagrabber.utils.Utils.logCollector; +import static awais.instagrabber.utils.Utils.settingsHelper; + +public final class ExportImportUtils { + public static final int FLAG_COOKIES = 1; + public static final int FLAG_FAVORITES = 1 << 1; + public static final int FLAG_SETTINGS = 1 << 2; + + @IntDef(value = {FLAG_COOKIES, FLAG_FAVORITES, FLAG_SETTINGS}, flag = true) + @interface ExportImportFlags {} + + public static void Export(@Nullable final String password, @ExportImportFlags final int flags, @NonNull final File filePath, + final FetchListener fetchListener) { + final String exportString = ExportImportUtils.getExportString(flags); + if (!Utils.isEmpty(exportString)) { + final boolean isPass = !Utils.isEmpty(password); + byte[] exportBytes = null; + + if (isPass) { + final byte[] passwordBytes = password.getBytes(); + final byte[] bytes = new byte[32]; + System.arraycopy(passwordBytes, 0, bytes, 0, Math.min(passwordBytes.length, 32)); + + try { + exportBytes = PasswordUtils.enc(exportString, bytes); + } catch (final Exception e) { + if (fetchListener != null) fetchListener.onResult(false); + if (logCollector != null) + logCollector.appendException(e, LogFile.UTILS_EXPORT, "Export::isPass"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } else { + exportBytes = Base64.encode(exportString.getBytes(), Base64.DEFAULT | Base64.NO_WRAP | Base64.NO_PADDING); + } + + if (exportBytes != null && exportBytes.length > 1) { + try (final FileOutputStream fos = new FileOutputStream(filePath)) { + fos.write(isPass ? 'A' : 'Z'); + fos.write(exportBytes); + if (fetchListener != null) fetchListener.onResult(true); + } catch (final Exception e) { + if (fetchListener != null) fetchListener.onResult(false); + if (logCollector != null) + logCollector.appendException(e, LogFile.UTILS_EXPORT, "Export::notPass"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } else if (fetchListener != null) fetchListener.onResult(false); + } + } + + public static void Import(@NonNull final Context context, @ExportImportFlags final int flags, @NonNull final File filePath, + final FetchListener fetchListener) { + try (final FileInputStream fis = new FileInputStream(filePath)) { + final int configType = fis.read(); + + final StringBuilder builder = new StringBuilder(); + int c; + while ((c = fis.read()) != -1) { + builder.append((char) c); + } + + if (configType == 'A') { + // password + final AppCompatEditText editText = new AppCompatEditText(context); + editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(32)}); + editText.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD); + new AlertDialog.Builder(context).setView(editText).setTitle(R.string.password).setPositiveButton(R.string.confirm, (dialog, which) -> { + final CharSequence text = editText.getText(); + if (!Utils.isEmpty(text)) { + try { + final byte[] passwordBytes = text.toString().getBytes(); + final byte[] bytes = new byte[32]; + System.arraycopy(passwordBytes, 0, bytes, 0, Math.min(passwordBytes.length, 32)); + saveToSettings(new String(PasswordUtils.dec(builder.toString(), bytes)), flags, fetchListener); + } catch (final Exception e) { + if (fetchListener != null) fetchListener.onResult(false); + if (logCollector != null) + logCollector.appendException(e, LogFile.UTILS_IMPORT, "Import::pass"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + } else + Toast.makeText(context, R.string.dialog_export_err_password_empty, Toast.LENGTH_SHORT).show(); + }).show(); + + } else if (configType == 'Z') { + saveToSettings(new String(Base64.decode(builder.toString(), Base64.DEFAULT | Base64.NO_PADDING | Base64.NO_WRAP)), + flags, fetchListener); + + } else { + Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); + if (fetchListener != null) fetchListener.onResult(false); + } + } catch (final Exception e) { + if (fetchListener != null) fetchListener.onResult(false); + if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_IMPORT, "Import"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } + + private static void saveToSettings(final String json, @ExportImportFlags final int flags, final FetchListener fetchListener) { + try { + final JSONObject jsonObject = new JSONObject(json); + + if ((flags & FLAG_SETTINGS) == FLAG_SETTINGS && jsonObject.has("settings")) { + final JSONObject objSettings = jsonObject.getJSONObject("settings"); + final Iterator keys = objSettings.keys(); + while (keys.hasNext()) { + final String key = keys.next(); + final Object val = objSettings.opt(key); + if (val instanceof String) { + settingsHelper.putString(key, (String) val); + } else if (val instanceof Integer) { + settingsHelper.putInteger(key, (int) val); + } else if (val instanceof Boolean) { + settingsHelper.putBoolean(key, (boolean) val); + } + } + } + + if ((flags & FLAG_COOKIES) == FLAG_COOKIES && jsonObject.has("cookies")) { + final JSONArray cookies = jsonObject.getJSONArray("cookies"); + final int cookiesLen = cookies.length(); + for (int i = 0; i < cookiesLen; ++i) { + final JSONObject cookieObject = cookies.getJSONObject(i); + Utils.dataBox.addUserCookie(new DataBox.CookieModel(cookieObject.getString("i"), + cookieObject.getString("u"), cookieObject.getString("c"))); + } + } + + if ((flags & FLAG_FAVORITES) == FLAG_FAVORITES && jsonObject.has("favs")) { + final JSONArray favs = jsonObject.getJSONArray("favs"); + final int favsLen = favs.length(); + for (int i = 0; i < favsLen; ++i) { + final JSONObject favsObject = favs.getJSONObject(i); + Utils.dataBox.addFavorite(new DataBox.FavoriteModel(favsObject.getString("q"), + favsObject.getLong("d"))); + } + } + + if (fetchListener != null) fetchListener.onResult(true); + + } catch (final Exception e) { + if (fetchListener != null) fetchListener.onResult(false); + if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_IMPORT, "saveToSettings"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } + + @Nullable + private static String getExportString(@ExportImportFlags final int flags) { + String result = null; + try { + final JSONObject jsonObject = new JSONObject(); + + String str; + if ((flags & FLAG_SETTINGS) == FLAG_SETTINGS) { + str = getSettings(); + if (str != null) jsonObject.put("settings", new JSONObject(str)); + } + + if ((flags & FLAG_COOKIES) == FLAG_COOKIES) { + str = getCookies(); + if (str != null) jsonObject.put("cookies", new JSONArray(str)); + } + + if ((flags & FLAG_FAVORITES) == FLAG_FAVORITES) { + str = getFavorites(); + if (str != null) jsonObject.put("favs", new JSONArray(str)); + } + + result = jsonObject.toString(); + } catch (final Exception e) { + if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_EXPORT, "getExportString"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + return result; + } + + @Nullable + private static String getSettings() { + String result = null; + + if (settingsHelper != null) { + try { + final JSONObject json = new JSONObject(); + json.put(Constants.APP_THEME, settingsHelper.getInteger(Constants.APP_THEME)); + json.put(Constants.APP_LANGUAGE, settingsHelper.getInteger(Constants.APP_LANGUAGE)); + json.put(Constants.PROFILE_FETCH_MODE, settingsHelper.getInteger(Constants.PROFILE_FETCH_MODE)); + + String str = settingsHelper.getString(Constants.FOLDER_PATH); + if (!Utils.isEmpty(str)) json.put(Constants.FOLDER_PATH, str); + + str = settingsHelper.getString(Constants.DATE_TIME_FORMAT); + if (!Utils.isEmpty(str)) json.put(Constants.DATE_TIME_FORMAT, str); + + str = settingsHelper.getString(Constants.DATE_TIME_SELECTION); + if (!Utils.isEmpty(str)) json.put(Constants.DATE_TIME_SELECTION, str); + + str = settingsHelper.getString(Constants.CUSTOM_DATE_TIME_FORMAT); + if (!Utils.isEmpty(str)) json.put(Constants.CUSTOM_DATE_TIME_FORMAT, str); + + json.put(Constants.DOWNLOAD_USER_FOLDER, settingsHelper.getBoolean(Constants.DOWNLOAD_USER_FOLDER)); + json.put(Constants.MUTED_VIDEOS, settingsHelper.getBoolean(Constants.MUTED_VIDEOS)); + json.put(Constants.BOTTOM_TOOLBAR, settingsHelper.getBoolean(Constants.BOTTOM_TOOLBAR)); + json.put(Constants.AUTOPLAY_VIDEOS, settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS)); + json.put(Constants.SHOW_FEED, settingsHelper.getBoolean(Constants.SHOW_FEED)); + json.put(Constants.AUTOLOAD_POSTS, settingsHelper.getBoolean(Constants.AUTOLOAD_POSTS)); + json.put(Constants.FOLDER_SAVE_TO, settingsHelper.getBoolean(Constants.FOLDER_SAVE_TO)); + + result = json.toString(); + } catch (final Exception e) { + result = null; + if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_EXPORT, "getSettings"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } + + return result; + } + + @Nullable + private static String getFavorites() { + String result = null; + if (Utils.dataBox != null) { + try { + final ArrayList allFavorites = Utils.dataBox.getAllFavorites(); + final int allFavoritesSize; + if (allFavorites != null && (allFavoritesSize = allFavorites.size()) > 0) { + final JSONArray jsonArray = new JSONArray(); + for (int i = 0; i < allFavoritesSize; i++) { + final DataBox.FavoriteModel favorite = allFavorites.get(i); + final JSONObject jsonObject = new JSONObject(); + jsonObject.put("q", favorite.getQuery()); + jsonObject.put("d", favorite.getDate()); + jsonArray.put(jsonObject); + } + result = jsonArray.toString(); + } + } catch (final Exception e) { + result = null; + if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_EXPORT, "getFavorites"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } + return result; + } + + @Nullable + private static String getCookies() { + String result = null; + if (Utils.dataBox != null) { + try { + final ArrayList allCookies = Utils.dataBox.getAllCookies(); + final int allCookiesSize; + if (allCookies != null && (allCookiesSize = allCookies.size()) > 0) { + final JSONArray jsonArray = new JSONArray(); + for (int i = 0; i < allCookiesSize; i++) { + final DataBox.CookieModel cookieModel = allCookies.get(i); + final JSONObject jsonObject = new JSONObject(); + jsonObject.put("i", cookieModel.getUid()); + jsonObject.put("u", cookieModel.getUsername()); + jsonObject.put("c", cookieModel.getCookie()); + jsonArray.put(jsonObject); + } + result = jsonArray.toString(); + } + } catch (final Exception e) { + result = null; + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } + return result; + } + + private final static class PasswordUtils { + private static final String cipherAlgo = "AES"; + private static final String cipherTran = "AES/CBC/PKCS5Padding"; + + private static byte[] dec(final String encrypted, final byte[] keyValue) throws Exception { + final Cipher cipher = Cipher.getInstance(cipherTran); + final SecretKeySpec secretKey = new SecretKeySpec(keyValue, cipherAlgo); + cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(new byte[16])); + return cipher.doFinal(Base64.decode(encrypted, Base64.DEFAULT | Base64.NO_PADDING | Base64.NO_WRAP)); + } + + private static byte[] enc(@NonNull final String str, final byte[] keyValue) throws Exception { + final Cipher cipher = Cipher.getInstance(cipherTran); + final SecretKeySpec secretKey = new SecretKeySpec(keyValue, cipherAlgo); + cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(new byte[16])); + final byte[] bytes = cipher.doFinal(str.getBytes()); + return Base64.encode(bytes, Base64.DEFAULT | Base64.NO_PADDING | Base64.NO_WRAP); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/FlavorTown.java b/app/src/main/java/awais/instagrabber/utils/FlavorTown.java new file mode 100755 index 00000000..8668cf9c --- /dev/null +++ b/app/src/main/java/awais/instagrabber/utils/FlavorTown.java @@ -0,0 +1,98 @@ +package awais.instagrabber.utils; + +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.net.Uri; +import android.os.AsyncTask; +import android.text.SpannableStringBuilder; +import android.text.method.LinkMovementMethod; +import android.text.style.RelativeSizeSpan; +import android.text.style.URLSpan; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.R; +import awais.instagrabber.interfaces.FetchListener; + +import static awais.instagrabber.utils.Utils.settingsHelper; + +public final class FlavorTown { + public static void updateCheck(@NonNull final Context context) { + new UpdateChecker(versionUrl -> { + new AlertDialog.Builder(context).setTitle(R.string.update_available).setNegativeButton(R.string.cancel, null) + .setPositiveButton(R.string.action_download, (dialog, which) -> { + try { + context.startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse(versionUrl))); + } catch (final ActivityNotFoundException e) { + // do nothing + } + }).show(); + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + public static void changelogCheck(@NonNull final Context context) { + if (settingsHelper.getInteger(Constants.PREV_INSTALL_VERSION) < BuildConfig.VERSION_CODE) { + new ChangelogFetcher(new FetchListener() { + private AlertDialog alertDialog; + private TextView textView; + + @Override + public void doBefore() { + final ViewGroup rootView = (ViewGroup) View.inflate(context, R.layout.layout_changelog_textview, null); + textView = (TextView) rootView.getChildAt(0); + textView.setMovementMethod(new LinkMovementMethod()); + alertDialog = new AlertDialog.Builder(context).setTitle(R.string.title_changelog).setView(rootView).create(); + } + + @Override + public void onResult(final CharSequence result) { + if (alertDialog != null && textView != null && !Utils.isEmpty(result)) { + final Resources resources = context.getResources(); + + final SpannableStringBuilder stringBuilder = new SpannableStringBuilder( + resources.getString(R.string.curr_version, BuildConfig.VERSION_NAME)) + .append('\n'); + + stringBuilder.setSpan(new RelativeSizeSpan(1.3f), 0, stringBuilder.length() - 1, 0); + + final int resLen = result.length(); + int versionTimes = 0; + + for (int i = 0; i < resLen; ++i) { + final char c = result.charAt(i); + + if (c == 'v' && i > 0) { + final char c1 = result.charAt(i - 1); + if (c1 == '\r' || c1 == '\n') { + if (++versionTimes == 4) break; + } + } + + stringBuilder.append(c); + } + + final String strReadMore = resources.getString(R.string.read_more); + stringBuilder.append('\n').append(strReadMore); + + final int sbLen = stringBuilder.length(); + stringBuilder.setSpan(new URLSpan("https://gitlab.com/AwaisKing/instagrabber/-/blob/master/CHANGELOG"), + sbLen - strReadMore.length(), sbLen, 0); + + textView.setText(stringBuilder, TextView.BufferType.SPANNABLE); + + alertDialog.show(); + } + + settingsHelper.putInteger(Constants.PREV_INSTALL_VERSION, BuildConfig.VERSION_CODE); + } + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/LocaleUtils.java b/app/src/main/java/awais/instagrabber/utils/LocaleUtils.java new file mode 100755 index 00000000..ad575bce --- /dev/null +++ b/app/src/main/java/awais/instagrabber/utils/LocaleUtils.java @@ -0,0 +1,70 @@ +package awais.instagrabber.utils; + +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.view.ContextThemeWrapper; + +import androidx.annotation.Nullable; + +import java.util.Locale; + +// taken from my app TESV Console Codes +public final class LocaleUtils { + private static Locale defaultLocale, currentLocale; + + public static void setLocale(Context baseContext) { + if (defaultLocale == null) defaultLocale = Locale.getDefault(); + + if (baseContext instanceof ContextThemeWrapper) + baseContext = ((ContextThemeWrapper) baseContext).getBaseContext(); + + final String lang = LocaleUtils.getCorrespondingLanguageCode(baseContext); + + currentLocale = Utils.isEmpty(lang) ? defaultLocale : new Locale(lang); + Locale.setDefault(currentLocale); + + final Resources res = baseContext.getResources(); + final Configuration config = res.getConfiguration(); + + config.locale = currentLocale; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + config.setLocale(currentLocale); + config.setLayoutDirection(currentLocale); + } + + res.updateConfiguration(config, res.getDisplayMetrics()); + } + + public static Locale getCurrentLocale() { + return currentLocale; + } + + public static void updateConfig(final ContextThemeWrapper wrapper) { + if (currentLocale != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + final Configuration configuration = new Configuration(); + configuration.locale = currentLocale; + configuration.setLocale(currentLocale); + wrapper.applyOverrideConfiguration(configuration); + } + } + + @Nullable + private static String getCorrespondingLanguageCode(final Context baseContext) { + if (Utils.settingsHelper == null) + Utils.settingsHelper = new SettingsHelper(baseContext); + + final int appLanguageIndex = Utils.settingsHelper.getInteger(Constants.APP_LANGUAGE); + + // todo keep adding languages till i die...... or find a big tiddy goth gf ;-; + if (appLanguageIndex == 1) return "en"; + if (appLanguageIndex == 2) return "fr"; + if (appLanguageIndex == 3) return "es"; + if (appLanguageIndex == 4) return "zh"; + if (appLanguageIndex == 5) return "in"; + if (appLanguageIndex == 6) return "it"; + + return null; + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/MyApps.java b/app/src/main/java/awais/instagrabber/utils/MyApps.java new file mode 100755 index 00000000..5d39568d --- /dev/null +++ b/app/src/main/java/awais/instagrabber/utils/MyApps.java @@ -0,0 +1,138 @@ +package awais.instagrabber.utils; + +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.res.Resources; +import android.net.Uri; +import android.os.Build; +import android.os.Process; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.GridView; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.AppCompatImageView; +import androidx.appcompat.widget.AppCompatTextView; + +import java.util.Random; + +import awais.instagrabber.R; + +public final class MyApps { + public final static Icons[] iconsList = Icons.values(); + + @SuppressWarnings("unused") + public enum Icons { + MEDIASCAN("awais.media.scanner", "mediaScanner", R.drawable.zzz_ms), + ADDME("awais.addme", "AddMe", R.drawable.zzz_adm), + LINKEDWORDS("awais.backworddictionary", "Linked Words", R.drawable.zzz_lw), + QUODB("awais.quodb", "QuoDB", R.drawable.zzz_qdb), + REVERSIFY("awais.reversify", "Reversify", R.drawable.zzz_rev), + REVERSIFY_LITE("awais.reversify.lite", "Reversify Lite", R.drawable.zzz_revl), + TESV("awais.skyrimconsole", "Skyrim Cheats", R.drawable.zzz_tesv); + private final int icon; + private final String name, pkg; + + Icons(final String pkg, final String name, final int icon) { + this.name = name; + this.pkg = pkg; + this.icon = icon; + } + } + + public static void openAppStore(@NonNull final Context context, final int position) { + context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + MyApps.iconsList[position].pkg))); + } + + public static void showAlertDialog(final Context context, final AdapterView.OnItemClickListener clickListener) { + final DialogInterface.OnCancelListener cancelListener = d -> { + if (clickListener != null) clickListener.onItemClick(null, null, -1, -1); + else Process.killProcess(Process.myPid()); + }; + if (new Random().nextDouble() < 0.420D) { + cancelListener.onCancel(null); + return; + } + final GridView gridView = new GridView(context); + gridView.setAdapter(new ImageAdapter(context)); + gridView.setNumColumns(3); + gridView.setOnItemClickListener(clickListener); + final AlertDialog dialog = new AlertDialog.Builder(context).setView(gridView).setTitle("Support my apps tho").create(); + dialog.setOnCancelListener(cancelListener); + dialog.show(); + } + + public static class ImageAdapter extends BaseAdapter { + private final Context context; + private final int size; + + public ImageAdapter(final Context context) { + this.context = context; + this.size = (int) (80 * Resources.getSystem().getDisplayMetrics().density); + } + + @Override + public int getCount() { + return iconsList.length; + } + + @Override + public Object getItem(final int position) { + return iconsList[position]; + } + + @Override + public long getItemId(final int position) { + return 0; + } + + public View getView(final int position, View convertView, final ViewGroup parent) { + final ViewHolder holder; + if (convertView == null) { + final LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.VERTICAL); + final AppCompatImageView imageView = new AppCompatImageView(context); + final AppCompatTextView textView = new AppCompatTextView(context); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) + textView.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY); + textView.setGravity(Gravity.CENTER_HORIZONTAL); + imageView.setAdjustViewBounds(true); + linearLayout.addView(imageView, LinearLayout.LayoutParams.MATCH_PARENT, size); + linearLayout.addView(textView); + final int padding = size >> 2; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) + linearLayout.setPaddingRelative(padding, padding, padding, padding); + else linearLayout.setPadding(padding, padding, padding, padding); + convertView = linearLayout; + convertView.setTag(holder = new ViewHolder(textView, imageView)); + } else + holder = (ViewHolder) convertView.getTag(); + + final Object item = getItem(position); + if (item instanceof Icons) { + final Icons icons = (Icons) item; + holder.title.setText(icons.name); + holder.icon.setImageResource(icons.icon); + } + return convertView; + } + + private final static class ViewHolder { + private final TextView title; + private final ImageView icon; + + private ViewHolder(final TextView title, final ImageView icon) { + this.title = title; + this.icon = icon; + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/SettingsHelper.java b/app/src/main/java/awais/instagrabber/utils/SettingsHelper.java new file mode 100755 index 00000000..2a09d438 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/utils/SettingsHelper.java @@ -0,0 +1,115 @@ +package awais.instagrabber.utils; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Build; + +import androidx.annotation.NonNull; +import androidx.annotation.StringDef; +import androidx.appcompat.app.AppCompatDelegate; + +import static awais.instagrabber.utils.Constants.APP_LANGUAGE; +import static awais.instagrabber.utils.Constants.APP_THEME; +import static awais.instagrabber.utils.Constants.AUTOLOAD_POSTS; +import static awais.instagrabber.utils.Constants.AUTOPLAY_VIDEOS; +import static awais.instagrabber.utils.Constants.BOTTOM_TOOLBAR; +import static awais.instagrabber.utils.Constants.COOKIE; +import static awais.instagrabber.utils.Constants.CUSTOM_DATE_TIME_FORMAT; +import static awais.instagrabber.utils.Constants.CUSTOM_DATE_TIME_FORMAT_ENABLED; +import static awais.instagrabber.utils.Constants.DATE_TIME_FORMAT; +import static awais.instagrabber.utils.Constants.DATE_TIME_SELECTION; +import static awais.instagrabber.utils.Constants.DOWNLOAD_USER_FOLDER; +import static awais.instagrabber.utils.Constants.FOLDER_PATH; +import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO; +import static awais.instagrabber.utils.Constants.MUTED_VIDEOS; +import static awais.instagrabber.utils.Constants.PREV_INSTALL_VERSION; +import static awais.instagrabber.utils.Constants.PROFILE_FETCH_MODE; +import static awais.instagrabber.utils.Constants.SHOW_FEED; +import static awais.instagrabber.utils.Constants.SHOW_QUICK_ACCESS_DIALOG; + +public final class SettingsHelper { + private final SharedPreferences sharedPreferences; + + public SettingsHelper(@NonNull final Context context) { + this.sharedPreferences = context.getSharedPreferences("settings", Context.MODE_PRIVATE); + } + + @NonNull + public String getString(@StringSettings final String key) { + final String stringDefault = getStringDefault(key); + if (sharedPreferences != null) return sharedPreferences.getString(key, stringDefault); + return stringDefault; + } + + public int getInteger(@IntegerSettings final String key) { + final int integerDefault = getIntegerDefault(key); + if (sharedPreferences != null) return sharedPreferences.getInt(key, integerDefault); + return integerDefault; + } + + public boolean getBoolean(@BooleanSettings final String key) { + final boolean booleanDefault = getBooleanDefault(key); + if (sharedPreferences != null) return sharedPreferences.getBoolean(key, booleanDefault); + return booleanDefault; + } + + @NonNull + private String getStringDefault(@StringSettings final String key) { + if (DATE_TIME_FORMAT.equals(key)) + return "hh:mm:ss a 'on' dd-MM-yyyy"; + if (DATE_TIME_SELECTION.equals(key)) + return "0;3;0"; + return ""; + } + + private int getIntegerDefault(@IntegerSettings final String key) { + if (APP_THEME.equals(key)) return getThemeCode(true); + if (PREV_INSTALL_VERSION.equals(key)) return -1; + return 0; + } + + private boolean getBooleanDefault(@BooleanSettings final String key) { + return BOTTOM_TOOLBAR.equals(key) || + AUTOPLAY_VIDEOS.equals(key) || + SHOW_QUICK_ACCESS_DIALOG.equals(key) || + MUTED_VIDEOS.equals(key); + } + + public int getThemeCode(final boolean fromHelper) { + int themeCode = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; + + if (!fromHelper && sharedPreferences != null) { + themeCode = sharedPreferences.getInt(APP_THEME, themeCode); + if (themeCode == 1) themeCode = AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; + else if (themeCode == 3) themeCode = AppCompatDelegate.MODE_NIGHT_NO; + else if (themeCode != 2) themeCode = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; + } + + if (themeCode == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM && Build.VERSION.SDK_INT < 29) + themeCode = AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; + + return themeCode; + } + + public void putString(@StringSettings final String key, final String val) { + if (sharedPreferences != null) sharedPreferences.edit().putString(key, val).apply(); + } + + public void putInteger(@IntegerSettings final String key, final int val) { + if (sharedPreferences != null) sharedPreferences.edit().putInt(key, val).apply(); + } + + public void putBoolean(@BooleanSettings final String key, final boolean val) { + if (sharedPreferences != null) sharedPreferences.edit().putBoolean(key, val).apply(); + } + + @StringDef({COOKIE, FOLDER_PATH, DATE_TIME_FORMAT, DATE_TIME_SELECTION, CUSTOM_DATE_TIME_FORMAT}) + public @interface StringSettings {} + + @StringDef({DOWNLOAD_USER_FOLDER, BOTTOM_TOOLBAR, FOLDER_SAVE_TO, AUTOPLAY_VIDEOS, SHOW_QUICK_ACCESS_DIALOG, MUTED_VIDEOS, + AUTOLOAD_POSTS, SHOW_FEED, CUSTOM_DATE_TIME_FORMAT_ENABLED}) + public @interface BooleanSettings {} + + @StringDef({APP_THEME, APP_LANGUAGE, PROFILE_FETCH_MODE, PREV_INSTALL_VERSION}) + public @interface IntegerSettings {} +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/UpdateChecker.java b/app/src/main/java/awais/instagrabber/utils/UpdateChecker.java new file mode 100755 index 00000000..0605af07 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/utils/UpdateChecker.java @@ -0,0 +1,75 @@ +package awais.instagrabber.utils; + +import android.os.AsyncTask; +import android.util.Log; + +import androidx.annotation.NonNull; + +import java.net.HttpURLConnection; +import java.net.URL; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.interfaces.FetchListener; + +public final class UpdateChecker extends AsyncTask { + private final FetchListener fetchListener; + private String versionUrl; + + public UpdateChecker(final FetchListener fetchListener) { + this.fetchListener = fetchListener; + } + + @NonNull + @Override + protected Boolean doInBackground(final Void... voids) { + final String UPDATE_BASE_URL = "https://gitlab.com/AwaisKing/instagrabber/-/releases/v"; + final String versionName = BuildConfig.VERSION_NAME; + final int index = versionName.indexOf('.'); + + try { + final int verMajor = Integer.parseInt(versionName.substring(0, index)); + + versionUrl = UPDATE_BASE_URL + (verMajor + 1) + ".0"; + + // check major version first + HttpURLConnection conn = (HttpURLConnection) new URL(versionUrl).openConnection(); + conn.setUseCaches(false); + conn.setRequestMethod("HEAD"); + conn.connect(); + + final int responseCode = conn.getResponseCode(); + conn.disconnect(); + + if (responseCode == HttpURLConnection.HTTP_OK) return true; + else { + final String substring = versionName.substring(index + 1); + final int verMinor = Integer.parseInt(substring) + 1; + + for (int i = verMinor; i < 10; ++i) { + versionUrl = UPDATE_BASE_URL + verMajor + '.' + i; + conn.disconnect(); + + conn = (HttpURLConnection) new URL(versionUrl).openConnection(); + conn.setUseCaches(false); + conn.setRequestMethod("HEAD"); + conn.connect(); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + conn.disconnect(); + return true; + } + } + } + } catch (final Exception e) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return false; + } + + @Override + protected void onPostExecute(final Boolean result) { + if (result != null && result && fetchListener != null) + fetchListener.onResult(versionUrl); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/UrlEncoder.java b/app/src/main/java/awais/instagrabber/utils/UrlEncoder.java new file mode 100755 index 00000000..4795ad97 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/utils/UrlEncoder.java @@ -0,0 +1,74 @@ +package awais.instagrabber.utils; + +import androidx.annotation.NonNull; + +import java.io.CharArrayWriter; +import java.util.BitSet; + +// same as java.net.URLEncoder +public final class UrlEncoder { + private static final BitSet dontNeedEncoding = new BitSet(256); + private static final int caseDiff = ('a' - 'A'); + + static { + int i; + for (i = 'a'; i <= 'z'; i++) dontNeedEncoding.set(i); + for (i = 'A'; i <= 'Z'; i++) dontNeedEncoding.set(i); + for (i = '0'; i <= '9'; i++) dontNeedEncoding.set(i); + dontNeedEncoding.set(' '); + dontNeedEncoding.set('-'); + dontNeedEncoding.set('_'); + dontNeedEncoding.set('.'); + dontNeedEncoding.set('*'); + } + + @NonNull + public static String encodeUrl(@NonNull final String s) { + final StringBuilder out = new StringBuilder(s.length()); + final CharArrayWriter charArrayWriter = new CharArrayWriter(); + + boolean needToChange = false; + for (int i = 0; i < s.length(); ) { + int c = s.charAt(i); + + if (dontNeedEncoding.get(c)) { + if (c == ' ') { + c = '+'; + needToChange = true; + } + + out.append((char) c); + i++; + } else { + do { + charArrayWriter.write(c); + if (c >= 0xD800 && c <= 0xDBFF && i + 1 < s.length()) { + final int d = s.charAt(i + 1); + if (d >= 0xDC00 && d <= 0xDFFF) { + charArrayWriter.write(d); + i++; + } + } + i++; + } while (i < s.length() && !dontNeedEncoding.get(c = s.charAt(i))); + + charArrayWriter.flush(); + + final byte[] ba = charArrayWriter.toString().getBytes(); + for (final byte b : ba) { + out.append('%'); + char ch = Character.forDigit((b >> 4) & 0xF, 16); + if (Character.isLetter(ch)) ch -= caseDiff; + out.append(ch); + ch = Character.forDigit(b & 0xF, 16); + if (Character.isLetter(ch)) ch -= caseDiff; + out.append(ch); + } + charArrayWriter.reset(); + needToChange = true; + } + } + + return (needToChange ? out.toString() : s); + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/Utils.java b/app/src/main/java/awais/instagrabber/utils/Utils.java new file mode 100755 index 00000000..83ec6f5d --- /dev/null +++ b/app/src/main/java/awais/instagrabber/utils/Utils.java @@ -0,0 +1,1270 @@ +package awais.instagrabber.utils; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.ContentResolver; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Environment; +import android.text.Editable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.style.RelativeSizeSpan; +import android.text.style.URLSpan; +import android.util.DisplayMetrics; +import android.util.Log; +import android.util.Pair; +import android.view.LayoutInflater; +import android.view.View; +import android.webkit.CookieManager; +import android.webkit.MimeTypeMap; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.core.app.ActivityCompat; +import androidx.core.app.NotificationManagerCompat; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.FragmentManager; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FilenameFilter; +import java.io.InputStreamReader; +import java.net.CookiePolicy; +import java.net.CookieStore; +import java.net.HttpCookie; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.regex.Pattern; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.R; +import awais.instagrabber.activities.Main; +import awais.instagrabber.asyncs.DownloadAsync; +import awais.instagrabber.asyncs.PostFetcher; +import awais.instagrabber.customviews.CommentMentionClickSpan; +import awais.instagrabber.databinding.DialogImportExportBinding; +import awais.instagrabber.models.BasePostModel; +import awais.instagrabber.models.FeedStoryModel; +import awais.instagrabber.models.HighlightModel; +import awais.instagrabber.models.IntentModel; +import awais.instagrabber.models.ProfileModel; +import awais.instagrabber.models.StoryModel; +import awais.instagrabber.models.direct_messages.DirectItemModel; +import awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemRavenMediaModel; +import awais.instagrabber.models.direct_messages.InboxThreadModel; +import awais.instagrabber.models.enums.DirectItemType; +import awais.instagrabber.models.enums.DownloadMethod; +import awais.instagrabber.models.enums.InboxReadState; +import awais.instagrabber.models.enums.IntentModelType; +import awais.instagrabber.models.enums.MediaItemType; +import awais.instagrabber.models.enums.RavenExpiringMediaType; +import awais.instagrabber.models.enums.RavenMediaViewType; +import awaisomereport.LogCollector; + +import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemActionLogModel; +import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemAnimatedMediaModel; +import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemLinkContext; +import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemLinkModel; +import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemMediaModel; +import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemReelShareModel; +import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemVideoCallEventModel; +import static awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemVoiceMediaModel; +import static awais.instagrabber.models.direct_messages.DirectItemModel.RavenExpiringMediaActionSummaryModel; +import static awais.instagrabber.utils.Constants.FOLDER_PATH; +import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO; + +public final class Utils { + public static LogCollector logCollector; + public static SettingsHelper settingsHelper; + public static DataBox dataBox; + public static boolean sessionVolumeFull = false; + @SuppressLint("StaticFieldLeak") + public static NotificationManagerCompat notificationManager; + public static final CookieManager COOKIE_MANAGER = CookieManager.getInstance(); + public static final String[] PERMS = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}; + public static final java.net.CookieManager NET_COOKIE_MANAGER = new java.net.CookieManager(null, CookiePolicy.ACCEPT_ALL); + public static final MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); + public static final String CHANNEL_ID = "InstaGrabber", CHANNEL_NAME = "Instagrabber", + NOTIF_GROUP_NAME = "awais.instagrabber.InstaNotif"; + public static boolean isChannelCreated = false; + public static boolean isInstagramInstalled = false; + public static String telegramPackage; + public static ClipboardManager clipboardManager; + public static DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics(); + public static SimpleDateFormat datetimeParser; + + public static void setupCookies(final String cookieRaw) { + if (cookieRaw != null && !isEmpty(cookieRaw)) { + final CookieStore cookieStore = NET_COOKIE_MANAGER.getCookieStore(); + try { + final URI uri1 = new URI("https://instagram.com"); + final URI uri2 = new URI("https://instagram.com/"); + for (final String cookie : cookieRaw.split(";")) { + final String[] strings = cookie.split("=", 2); + final HttpCookie httpCookie = new HttpCookie(strings[0].trim(), strings[1].trim()); + httpCookie.setDomain("instagram.com"); + httpCookie.setPath("/"); + httpCookie.setVersion(0); + cookieStore.add(uri1, httpCookie); + cookieStore.add(uri2, httpCookie); + } + } catch (final URISyntaxException e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.UTILS, "setupCookies"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } + } + + @Nullable + public static String getUserIdFromCookie(final String cookie) { + if (!isEmpty(cookie)) { + final int uidIndex = cookie.indexOf("ds_user_id"); + if (uidIndex > 0) { + final int uidEndIndex = cookie.indexOf(';', uidIndex + 10); + if (uidEndIndex > 0) { + final String uid = cookie.substring(uidIndex + 11, uidEndIndex); + return !isEmpty(uid) ? uid : null; + } + } + } + return null; + } + + @Nullable + public static IntentModel stripString(@NonNull String clipString) { + final int wwwDel = clipString.contains("www.") ? 4 : 0; + final boolean isHttps = clipString.startsWith("https"); + + IntentModelType type = IntentModelType.UNKNOWN; + if (clipString.contains("instagram.com/")) { + clipString = clipString.substring((isHttps ? 22 : 21) + wwwDel); + + final char firstChar = clipString.charAt(0); + if ((firstChar == 'p' || firstChar == 'P') && clipString.charAt(1) == '/') { + clipString = clipString.substring(2); + type = IntentModelType.POST; + } else if (clipString.startsWith("explore/tags/")) { + clipString = clipString.substring(13); + type = IntentModelType.HASHTAG; + } + + clipString = cleanString(clipString); + } else if (clipString.contains("ig.me/u/")) { + clipString = clipString.substring((isHttps ? 16 : 15) + wwwDel); + clipString = cleanString(clipString); + type = IntentModelType.USERNAME; + + } else return null; + + final int clipLen = clipString.length() - 1; + if (clipString.charAt(clipLen) == '/') + clipString = clipString.substring(0, clipLen); + + return new IntentModel(type, clipString); + } + + @NonNull + public static String cleanString(@NonNull final String clipString) { + final int queryIndex = clipString.indexOf('?'); + final int paramIndex = clipString.indexOf('#'); + int startIndex = -1; + if (queryIndex > 0 && paramIndex > 0) { + if (queryIndex < paramIndex) startIndex = queryIndex; + else if (paramIndex < queryIndex) startIndex = paramIndex; + } else if (queryIndex == -1 && paramIndex > 0) startIndex = paramIndex; + else if (paramIndex == -1 && queryIndex > 0) startIndex = queryIndex; + return startIndex != -1 ? clipString.substring(0, startIndex) : clipString; + } + + @NonNull + public static CharSequence getMentionText(@NonNull final CharSequence text) { + final int commentLength = text.length(); + final SpannableStringBuilder stringBuilder = new SpannableStringBuilder(text, 0, commentLength); + + for (int i = 0; i < commentLength; ++i) { + char currChar = text.charAt(i); + + if (currChar == '@' || currChar == '#') { + final int startLen = i; + + do { + if (++i == commentLength) break; + currChar = text.charAt(i); + + if (currChar == '.') { + final char nextChar = text.charAt(i + 1); + if (nextChar == '.' || nextChar == ' ' || nextChar == '#' || nextChar == '@' || nextChar == '/' + || nextChar == '\r' || nextChar == '\n') { + break; + } + } + + // for merged hashtags + if (currChar == '#') { + --i; + break; + } + } while (currChar != ' ' && currChar != '\r' && currChar != '\n' && currChar != '>' && currChar != '<' + && currChar != ':' && currChar != ';' && currChar != '\'' && currChar != '"' && currChar != '[' + && currChar != ']' && currChar != '\\' && currChar != '=' && currChar != '-' && currChar != '!' + && currChar != '$' && currChar != '%' && currChar != '^' && currChar != '&' && currChar != '*' + && currChar != '(' && currChar != ')' && currChar != '{' && currChar != '}' && currChar != '/' + && currChar != '|' && currChar != '?' && currChar != '`' && currChar != '~'); + + final int endLen = currChar != '#' ? i : i + 1; // for merged hashtags + stringBuilder.setSpan(new CommentMentionClickSpan(), startLen, + Math.min(commentLength, endLen), // fixed - crash when end index is greater than comment length ( @kernoeb ) + Spanned.SPAN_EXCLUSIVE_INCLUSIVE); + } + } + + return stringBuilder; + } + + @Nullable + public static String getHighQualityPost(final JSONArray resources, final boolean isVideo) { + try { + final int resourcesLen = resources.length(); + + final String[] sources = new String[resourcesLen]; + int lastResMain = 0, lastIndexMain = -1; + int lastResBase = 0, lastIndexBase = -1; + for (int i = 0; i < resourcesLen; ++i) { + final JSONObject item = resources.getJSONObject(i); + if (item != null && (!isVideo || item.has(Constants.EXTRAS_PROFILE))) { + sources[i] = item.getString("src"); + final int currRes = item.getInt("config_width") * item.getInt("config_height"); + + final String profile = isVideo ? item.getString(Constants.EXTRAS_PROFILE) : null; + + if (!isVideo || "MAIN".equals(profile)) { + if (currRes > lastResMain) { + lastResMain = currRes; + lastIndexMain = i; + } + } else if ("BASELINE".equals(profile)) { + if (currRes > lastResBase) { + lastResBase = currRes; + lastIndexBase = i; + } + } + } + } + + if (lastIndexMain >= 0) return sources[lastIndexMain]; + else if (lastIndexBase >= 0) return sources[lastIndexBase]; + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.UTILS, "getHighQualityPost", + new Pair<>("resourcesNull", resources == null), + new Pair<>("isVideo", isVideo)); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + return null; + } + + public static String getHighQualityImage(final JSONObject resources) { + String src = null; + try { + if (resources.has("display_resources")) src = getHighQualityPost(resources.getJSONArray("display_resources"), false); + if (src == null) return resources.getString("display_url"); + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.UTILS, "getHighQualityImage", + new Pair<>("resourcesNull", resources == null)); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + return src; + } + + public static String getItemThumbnail(@NonNull final JSONArray jsonArray) { + String thumbnail = null; + final int imageResLen = jsonArray.length(); + + for (int i = 0; i < imageResLen; ++i) { + final JSONObject imageResource = jsonArray.optJSONObject(i); + try { + final int width = imageResource.getInt("width"); + final int height = imageResource.getInt("height"); + final float ratio = Float.parseFloat(String.format(Locale.ENGLISH, "%.2f", (float) height / width)); + if (ratio >= 0.95f && ratio <= 1.0f) { + thumbnail = imageResource.getString("url"); + break; + } + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.UTILS, "getItemThumbnail"); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + thumbnail = null; + } + } + + if (Utils.isEmpty(thumbnail)) thumbnail = jsonArray.optJSONObject(0).optString("url"); + + return thumbnail; + } + + @Nullable + public static String getThumbnailUrl(@NonNull final JSONObject mediaObj, final MediaItemType mediaType) throws Exception { + String thumbnail = null; + + if (mediaType == MediaItemType.MEDIA_TYPE_IMAGE || mediaType == MediaItemType.MEDIA_TYPE_VIDEO) { + final JSONObject imageVersions = mediaObj.optJSONObject("image_versions2"); + if (imageVersions != null) + thumbnail = Utils.getItemThumbnail(imageVersions.getJSONArray("candidates")); + + } else if (mediaType == MediaItemType.MEDIA_TYPE_SLIDER) { + final JSONArray carouselMedia = mediaObj.optJSONArray("carousel_media"); + if (carouselMedia != null) thumbnail = Utils.getItemThumbnail(carouselMedia.getJSONObject(0) + .getJSONObject("image_versions2").getJSONArray("candidates")); + } + + return thumbnail; + } + + @Nullable + public static MediaItemType getMediaItemType(final int mediaType) { + if (mediaType == 1) return MediaItemType.MEDIA_TYPE_IMAGE; + if (mediaType == 2) return MediaItemType.MEDIA_TYPE_VIDEO; + if (mediaType == 8) return MediaItemType.MEDIA_TYPE_SLIDER; + if (mediaType == 11) return MediaItemType.MEDIA_TYPE_VOICE; + return null; + } + + public static DirectItemMediaModel getDirectMediaModel(final JSONObject mediaObj) throws Exception { + final DirectItemMediaModel mediaModel; + if (mediaObj == null) mediaModel = null; + else { + final JSONObject userObj = mediaObj.optJSONObject("user"); + + ProfileModel user = null; + if (userObj != null) { + user = new ProfileModel( + userObj.getBoolean("is_private"), + userObj.optBoolean("is_verified"), + String.valueOf(userObj.get("pk")), + userObj.getString("username"), + userObj.getString("full_name"), + null, null, + userObj.getString("profile_pic_url"), + null, 0, 0, 0); + } + + final MediaItemType mediaType = getMediaItemType(mediaObj.optInt("media_type", -1)); + + String id = mediaObj.optString("id"); + if (Utils.isEmpty(id)) id = null; + + mediaModel = new DirectItemMediaModel(mediaType, + mediaObj.optLong("expiring_at"), + mediaObj.optLong("pk"), + id, + getThumbnailUrl(mediaObj, mediaType), + user); + } + return mediaModel; + } + + private static DirectItemType getDirectItemType(final String itemType) { + if ("placeholder".equals(itemType)) return DirectItemType.PLACEHOLDER; + if ("media".equals(itemType)) return DirectItemType.MEDIA; + if ("link".equals(itemType)) return DirectItemType.LINK; + if ("like".equals(itemType)) return DirectItemType.LIKE; + if ("reel_share".equals(itemType)) return DirectItemType.REEL_SHARE; + if ("media_share".equals(itemType)) return DirectItemType.MEDIA_SHARE; + if ("action_log".equals(itemType)) return DirectItemType.ACTION_LOG; + if ("raven_media".equals(itemType)) return DirectItemType.RAVEN_MEDIA; + if ("profile".equals(itemType)) return DirectItemType.PROFILE; + if ("video_call_event".equals(itemType)) return DirectItemType.VIDEO_CALL_EVENT; + if ("animated_media".equals(itemType)) return DirectItemType.ANIMATED_MEDIA; + if ("voice_media".equals(itemType)) return DirectItemType.VOICE_MEDIA; + //if ("story_share".equals(itemType)) return DirectItemType.STORY_SHARE; + return DirectItemType.TEXT; + } + + @NonNull + public static InboxThreadModel createInboxThreadModel(@NonNull final JSONObject data, final boolean inThreadView) throws Exception { + final InboxReadState readState = data.getInt("read_state") == 0 ? InboxReadState.STATE_READ : InboxReadState.STATE_UNREAD; + final String threadType = data.getString("thread_type");// private = dms, [??] = group + + final String threadId = data.getString("thread_id"); + final String threadV2Id = data.getString("thread_v2_id"); + final String threadTitle = data.getString("thread_title"); + + final String threadNewestCursor = data.getString("newest_cursor"); + final String threadOldestCursor = data.getString("oldest_cursor"); + final String threadNextCursor = data.has("next_cursor") ? data.getString("next_cursor") : null; + final String threadPrevCursor = data.has("prev_cursor") ? data.getString("prev_cursor") : null; + + final boolean threadHasOlder = data.getBoolean("has_older"); + final boolean threadHasNewer = data.getBoolean("has_newer"); + + final long lastActivityAt = data.optLong("last_activity_at"); + final boolean named = data.optBoolean("named"); + final boolean muted = data.optBoolean("muted"); + final boolean isPin = data.optBoolean("is_pin"); + final boolean isSpam = data.optBoolean("is_spam"); + final boolean isGroup = data.optBoolean("is_group"); + final boolean pending = data.optBoolean("pending"); + final boolean archived = data.optBoolean("archived"); + final boolean canonical = data.optBoolean("canonical"); + + final JSONArray users = data.getJSONArray("users"); + final int usersLen = users.length(); + + final ProfileModel[] userModels = new ProfileModel[usersLen]; + for (int j = 0; j < usersLen; ++j) { + final JSONObject userObject = users.getJSONObject(j); + userModels[j] = new ProfileModel(userObject.getBoolean("is_private"), + userObject.optBoolean("is_verified"), + String.valueOf(userObject.get("pk")), + userObject.getString("username"), + userObject.getString("full_name"), + null, null, + userObject.getString("profile_pic_url"), + null, 0, 0, 0); + } + + final JSONArray items = data.getJSONArray("items"); + final int itemsLen = items.length(); + + final ArrayList itemModels = new ArrayList<>(itemsLen); + for (int i = 0; i < itemsLen; ++i) { + final JSONObject itemObject = items.getJSONObject(i); + + CharSequence text = null; + ProfileModel profileModel = null; + DirectItemLinkModel linkModel = null; + DirectItemMediaModel directMedia = null; + DirectItemReelShareModel reelShareModel = null; + DirectItemActionLogModel actionLogModel = null; + DirectItemAnimatedMediaModel animatedMediaModel = null; + DirectItemVoiceMediaModel voiceMediaModel = null; + DirectItemRavenMediaModel ravenMediaModel = null; + DirectItemVideoCallEventModel videoCallEventModel = null; + + final DirectItemType itemType = getDirectItemType(itemObject.getString("item_type")); + switch (itemType) { + case ANIMATED_MEDIA: { + final JSONObject animatedMedia = itemObject.getJSONObject("animated_media"); + final JSONObject stickerImage = animatedMedia.getJSONObject("images").getJSONObject("fixed_height"); + + animatedMediaModel = new DirectItemAnimatedMediaModel(animatedMedia.getBoolean("is_random"), + animatedMedia.getBoolean("is_sticker"), animatedMedia.getString("id"), + stickerImage.getString("url"), stickerImage.optString("webp"), stickerImage.optString("mp4"), + stickerImage.getInt("height"), stickerImage.getInt("width")); + } + break; + + case VOICE_MEDIA: { + final JSONObject voiceMedia = itemObject.getJSONObject("voice_media").getJSONObject("media"); + final JSONObject audio = voiceMedia.getJSONObject("audio"); + + int[] waveformData = null; + final JSONArray waveformDataArray = audio.optJSONArray("waveform_data"); + if (waveformDataArray != null) { + final int waveformDataLen = waveformDataArray.length(); + waveformData = new int[waveformDataLen]; + // 0.011775206 + for (int j = 0; j < waveformDataLen; ++j) { + waveformData[j] = (int) (waveformDataArray.optDouble(j) * 10); + } + } + + voiceMediaModel = new DirectItemVoiceMediaModel(voiceMedia.getString("id"), + audio.getString("audio_src"), audio.getLong("duration"), + waveformData); + } + break; + + case LINK: { + final JSONObject linkObj = itemObject.getJSONObject("link"); + + DirectItemLinkContext itemLinkContext = null; + final JSONObject linkContext = linkObj.optJSONObject("link_context"); + if (linkContext != null) { + itemLinkContext = new DirectItemLinkContext( + linkContext.getString("link_url"), + linkContext.optString("link_title"), + linkContext.optString("link_summary"), + linkContext.optString("link_image_url") + ); + } + + linkModel = new DirectItemLinkModel(linkObj.getString("text"), + linkObj.getString("client_context"), + linkObj.getString("mutation_token"), + itemLinkContext); + } + break; + + case REEL_SHARE: { + final JSONObject reelShare = itemObject.getJSONObject("reel_share"); + Log.d("AWAISKING_APP", "(rs) itemObject: " + itemObject); // todo + reelShareModel = new DirectItemReelShareModel( + reelShare.optBoolean("is_reel_persisted"), + reelShare.getLong("reel_owner_id"), + reelShare.getString("text"), + reelShare.getString("type"), + reelShare.getString("reel_type"), + reelShare.optString("reel_name"), + reelShare.optString("reel_id"), + getDirectMediaModel(reelShare.optJSONObject("media"))); + } + break; + + case RAVEN_MEDIA: { + final JSONObject visualMedia = itemObject.getJSONObject("visual_media"); + + final JSONArray seenUserIdsArray = visualMedia.getJSONArray("seen_user_ids"); + final int seenUsersLen = seenUserIdsArray.length(); + final String[] seenUserIds = new String[seenUsersLen]; + for (int j = 0; j < seenUsersLen; j++) seenUserIds[j] = seenUserIdsArray.getString(j); + + RavenExpiringMediaActionSummaryModel expiringSummaryModel = null; + final JSONObject actionSummary = visualMedia.optJSONObject("expiring_media_action_summary"); + if (actionSummary != null) expiringSummaryModel = new RavenExpiringMediaActionSummaryModel( + actionSummary.getLong("timestamp"), actionSummary.getInt("count"), + getExpiringMediaType(actionSummary.getString("type"))); + + final RavenMediaViewType viewType; + final String viewMode = visualMedia.getString("view_mode"); + switch (viewMode) { + case "replayable": + viewType = RavenMediaViewType.REPLAYABLE; + break; + case "permanent": + viewType = RavenMediaViewType.PERMANENT; + break; + case "once": + default: + viewType = RavenMediaViewType.ONCE; + } + + ravenMediaModel = new DirectItemRavenMediaModel( + visualMedia.getLong(viewType == RavenMediaViewType.PERMANENT ? "url_expire_at_secs" : "replay_expiring_at_us"), + visualMedia.optInt("playback_duration_secs"), + visualMedia.getInt("seen_count"), + seenUserIds, + viewType, + getDirectMediaModel(visualMedia.optJSONObject("media")), + expiringSummaryModel); + + } + break; + + case VIDEO_CALL_EVENT: { + final JSONObject videoCallEvent = itemObject.getJSONObject("video_call_event"); + videoCallEventModel = new DirectItemVideoCallEventModel(videoCallEvent.getLong("vc_id"), + videoCallEvent.optBoolean("thread_has_audio_only_call"), + videoCallEvent.getString("action"), + videoCallEvent.getString("description")); + } + break; + + case PROFILE: { + final JSONObject profile = itemObject.getJSONObject("profile"); + profileModel = new ProfileModel(profile.getBoolean("is_private"), + profile.getBoolean("is_verified"), + Long.toString(profile.getLong("pk")), + profile.getString("username"), + profile.getString("full_name"), + null, null, + profile.getString("profile_pic_url"), + null, 0, 0, 0); + } + break; + + case PLACEHOLDER: { + final JSONObject placeholder = itemObject.getJSONObject("placeholder"); + + final String title = placeholder.getString("title"); + final String message = placeholder.getString("message"); + + final SpannableString spannableString = new SpannableString(title + '\n' + message); + spannableString.setSpan(new RelativeSizeSpan(1.15f), 0, title.length(), 0); + + text = hasMentions(message) ? getMentionText(spannableString) : spannableString; + } + break; + + case ACTION_LOG: + if (inThreadView && itemObject.optInt("hide_in_thread", 0) != 0) + // prevents empty viewholders when in thread view mode + continue; + final JSONObject actionLog = itemObject.getJSONObject("action_log"); + actionLogModel = new DirectItemActionLogModel(actionLog.getString("description") + // todo add bold , text_attributes objects [find out how tf to implement them] + ); + break; + + case MEDIA_SHARE: + directMedia = getDirectMediaModel(itemObject.getJSONObject("media_share")); + break; + + case MEDIA: + directMedia = getDirectMediaModel(itemObject.optJSONObject("media")); + break; + + case LIKE: + text = new SpannableString(itemObject.getString("like")); + ((SpannableString) text).setSpan(new RelativeSizeSpan(15f), 0, text.length(), 0); + break; + + /*case STORY_SHARE: + if*/ + + case TEXT: + if (!itemObject.has("text")) + Log.d("AWAISKING_APP", "itemObject: " + itemObject); // todo + text = itemObject.optString("text"); + break; + } + + itemModels.add(new DirectItemModel( + itemObject.getLong("user_id"), + itemObject.getLong("timestamp"), + itemObject.getString("item_id"), + itemType, + text, + linkModel, + profileModel, + reelShareModel, + directMedia, + actionLogModel, + voiceMediaModel, + ravenMediaModel, + videoCallEventModel, + animatedMediaModel)); + } + + itemModels.trimToSize(); + + return new InboxThreadModel(readState, threadId, threadV2Id, threadType, threadTitle, + threadNewestCursor, threadOldestCursor, threadNextCursor, threadPrevCursor, + null, // todo + userModels, + null, // todo + itemModels.toArray(new DirectItemModel[0]), + muted, isPin, named, canonical, + pending, threadHasOlder, threadHasNewer, isSpam, isGroup, archived, lastActivityAt); + } + + private static RavenExpiringMediaType getExpiringMediaType(final String type) { + if ("raven_sent".equals(type)) return RavenExpiringMediaType.RAVEN_SENT; + if ("raven_opened".equals(type)) return RavenExpiringMediaType.RAVEN_OPENED; + if ("raven_blocked".equals(type)) return RavenExpiringMediaType.RAVEN_BLOCKED; + if ("raven_sending".equals(type)) return RavenExpiringMediaType.RAVEN_SENDING; + if ("raven_replayed".equals(type)) return RavenExpiringMediaType.RAVEN_REPLAYED; + if ("raven_delivered".equals(type)) return RavenExpiringMediaType.RAVEN_DELIVERED; + if ("raven_suggested".equals(type)) return RavenExpiringMediaType.RAVEN_SUGGESTED; + if ("raven_screenshot".equals(type)) return RavenExpiringMediaType.RAVEN_SCREENSHOT; + if ("raven_cannot_deliver".equals(type)) return RavenExpiringMediaType.RAVEN_CANNOT_DELIVER; + //if ("raven_unknown".equals(type)) [default?] + return RavenExpiringMediaType.RAVEN_UNKNOWN; + } + + public static int convertDpToPx(final float dp) { + if (displayMetrics == null) + displayMetrics = Resources.getSystem().getDisplayMetrics(); + return Math.round((dp * displayMetrics.densityDpi) / 160.0f); + } + + public static void changeTheme() { + int themeCode = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; // this is fallback / default + + if (settingsHelper != null) themeCode = settingsHelper.getThemeCode(false); + + if (themeCode == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM && Build.VERSION.SDK_INT < 29) + themeCode = AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; + + AppCompatDelegate.setDefaultNightMode(themeCode); + } + + public static void setTooltipText(final View view, @StringRes final int tooltipTextRes) { + if (view != null && tooltipTextRes != 0 && tooltipTextRes != -1) { + final Context context = view.getContext(); + final String tooltipText = context.getResources().getString(tooltipTextRes); + + if (Build.VERSION.SDK_INT >= 26) view.setTooltipText(tooltipText); + else view.setOnLongClickListener(v -> { + Toast.makeText(context, tooltipText, Toast.LENGTH_SHORT).show(); + return true; + }); + } + } + + @NonNull + public static String millisToString(final long timeMs) { + final long totalSeconds = timeMs / 1000; + + final long seconds = totalSeconds % 60; + final long minutes = totalSeconds / 60 % 60; + final long hours = totalSeconds / 3600; + + final String strSec = Long.toString(seconds); + final String strMin = Long.toString(minutes); + + final String strRetSec = strSec.length() > 1 ? strSec : "0" + seconds; + final String strRetMin = strMin.length() > 1 ? strMin : "0" + minutes; + + final String retMinSec = strRetMin + ':' + strRetSec; + + if (hours > 0) + return Long.toString(hours) + ':' + retMinSec; + return retMinSec; + } + + // extracted from String class + public static int indexOfChar(@NonNull final CharSequence sequence, final int ch, final int startIndex) { + final int max = sequence.length(); + if (startIndex < max) { + if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { + for (int i = startIndex; i < max; i++) if (sequence.charAt(i) == ch) return i; + } else if (Character.isValidCodePoint(ch)) { + final char hi = (char) ((ch >>> 10) + (Character.MIN_HIGH_SURROGATE - (Character.MIN_SUPPLEMENTARY_CODE_POINT >>> 10))); + final char lo = (char) ((ch & 0x3ff) + Character.MIN_LOW_SURROGATE); + for (int i = startIndex; i < max; i++) + if (sequence.charAt(i) == hi && sequence.charAt(i + 1) == lo) return i; + } + } + return -1; + } + + public static boolean hasMentions(final CharSequence text) { + if (isEmpty(text)) return false; + return Utils.indexOfChar(text, '@', 0) != -1 || Utils.indexOfChar(text, '#', 0) != -1; + } + + public static void copyText(final Context context, final CharSequence string) { + final boolean ctxNotNull = context != null; + if (ctxNotNull && clipboardManager == null) + clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + + int toastMessage = R.string.clipboard_error; + if (clipboardManager != null) { + clipboardManager.setPrimaryClip(ClipData.newPlainText(Utils.CHANNEL_NAME, string)); + toastMessage = R.string.clipboard_copied; + } + if (ctxNotNull) Toast.makeText(context, toastMessage, Toast.LENGTH_SHORT).show(); + } + + @NonNull + public static String readFromConnection(@NonNull final HttpURLConnection conn) throws Exception { + final StringBuilder sb = new StringBuilder(); + try (final BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()))) { + String line; + while ((line = br.readLine()) != null) sb.append(line).append('\n'); + } + return sb.toString(); + } + + public static void batchDownload(@NonNull final Context context, @Nullable final String username, final DownloadMethod method, + final List itemsToDownload) { + if (settingsHelper == null) settingsHelper = new SettingsHelper(context); + + if (itemsToDownload == null || itemsToDownload.size() < 1) return; + + if (ContextCompat.checkSelfPermission(context, Utils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) + batchDownloadImpl(context, username, method, itemsToDownload); + else if (context instanceof Activity) + ActivityCompat.requestPermissions((Activity) context, Utils.PERMS, 8020); + } + + private static void batchDownloadImpl(@NonNull final Context context, @Nullable final String username, + final DownloadMethod method, final List itemsToDownload) { + File dir = new File(Environment.getExternalStorageDirectory(), "Download"); + + if (settingsHelper.getBoolean(FOLDER_SAVE_TO)) { + final String customPath = settingsHelper.getString(FOLDER_PATH); + if (!Utils.isEmpty(customPath)) dir = new File(customPath); + } + + if (settingsHelper.getBoolean(Constants.DOWNLOAD_USER_FOLDER) && !isEmpty(username)) + dir = new File(dir, username); + + if (dir.exists() || dir.mkdirs()) { + final Main main = method != DownloadMethod.DOWNLOAD_FEED && context instanceof Main ? (Main) context : null; + + final int itemsToDownloadSize = itemsToDownload.size(); + + final File finalDir = dir; + for (int i = itemsToDownloadSize - 1; i >= 0; i--) { + final BasePostModel selectedItem = itemsToDownload.get(i); + + if (main == null) { + new DownloadAsync(context, + selectedItem.getDisplayUrl(), + getDownloadSaveFile(finalDir, selectedItem, ""), + null).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + + } else { + new PostFetcher(selectedItem.getShortCode(), result -> { + if (result != null) { + final int resultsSize = result.length; + final boolean multiResult = resultsSize > 1; + + for (int j = 0; j < resultsSize; j++) { + final BasePostModel model = result[j]; + final File saveFile = getDownloadSaveFile(finalDir, model, multiResult ? "_slide_" + (j + 1) : ""); + + new DownloadAsync(context, + model.getDisplayUrl(), + saveFile, + file -> { + model.setDownloaded(true); + main.mainHelper.deselectSelection(selectedItem); + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + } else { + main.mainHelper.deselectSelection(selectedItem); + } + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + } + } else + Toast.makeText(context, R.string.error_creating_folders, Toast.LENGTH_SHORT).show(); + } + + @NonNull + private static File getDownloadSaveFile(final File finalDir, @NonNull final BasePostModel model, final String sliderPrefix) { + final String displayUrl = model.getDisplayUrl(); + return new File(finalDir, model.getPostId() + '_' + model.getTimestamp() + sliderPrefix + + getExtensionFromModel(displayUrl, model)); + } + + @NonNull + public static String getExtensionFromModel(@NonNull final String url, final Object model) { + final String extension; + final int index = url.indexOf('?'); + + if (index != -1) extension = url.substring(index - 4, index); + else { + final boolean isVideo; + if (model instanceof StoryModel) + isVideo = ((StoryModel) model).getItemType() == MediaItemType.MEDIA_TYPE_VIDEO; + else if (model instanceof BasePostModel) + isVideo = ((BasePostModel) model).getItemType() == MediaItemType.MEDIA_TYPE_VIDEO; + else + isVideo = false; + extension = isVideo || url.contains(".mp4") ? ".mp4" : ".jpg"; + } + + return extension; + } + + public static void checkExistence(final File downloadDir, final File customDir, final String username, final boolean isSlider, + final int sliderIndex, @NonNull final BasePostModel model) { + boolean exists = false; + + try { + final String displayUrl = model.getDisplayUrl(); + final int index = displayUrl.indexOf('?'); + + final String fileName = model.getPostId() + '_' + model.getTimestamp(); + final String extension = displayUrl.substring(index - 4, index); + + final String fileWithoutPrefix = fileName + extension; + exists = new File(downloadDir, fileWithoutPrefix).exists(); + if (!exists) { + if (customDir != null) exists = new File(customDir, fileWithoutPrefix).exists(); + if (!exists && !Utils.isEmpty(username)) { + exists = new File(new File(downloadDir, username), fileWithoutPrefix).exists(); + } + if (!exists && customDir != null) + exists = new File(new File(customDir, username), fileWithoutPrefix).exists(); + } + + if (!exists && isSlider && sliderIndex != -1) { + final String fileWithPrefix = fileName + "_slide_[\\d]+" + extension; + final FilenameFilter filenameFilter = (dir, name) -> Pattern.matches(fileWithPrefix, name); + + File[] files = downloadDir.listFiles(filenameFilter); + if ((files == null || files.length < 1) && customDir != null) + files = customDir.listFiles(filenameFilter); + + if (files != null && files.length >= 1) exists = true; + } + } catch (final Exception e) { + if (logCollector != null) + logCollector.appendException(e, LogCollector.LogFile.UTILS, "checkExistence", + new Pair<>("isSlider", isSlider), + new Pair<>("sliderIndex", sliderIndex), + new Pair<>("model", model)); + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + model.setDownloaded(exists); + } + + public static boolean hasKey(final String key, final String username, final String name) { + if (!Utils.isEmpty(key)) { + final boolean hasUserName = username != null && username.toLowerCase().contains(key); + if (!hasUserName && name != null) return name.toLowerCase().contains(key); + } + return true; + } + + public static void showImportExportDialog(final Context context) { + final DialogImportExportBinding importExportBinding = DialogImportExportBinding.inflate(LayoutInflater.from(context)); + + final View passwordParent = (View) importExportBinding.cbPassword.getParent(); + final View exportLoginsParent = (View) importExportBinding.cbExportLogins.getParent(); + final View exportFavoritesParent = (View) importExportBinding.cbExportFavorites.getParent(); + final View exportSettingsParent = (View) importExportBinding.cbExportSettings.getParent(); + final View importLoginsParent = (View) importExportBinding.cbImportLogins.getParent(); + final View importFavoritesParent = (View) importExportBinding.cbImportFavorites.getParent(); + final View importSettingsParent = (View) importExportBinding.cbImportSettings.getParent(); + + importExportBinding.cbPassword.setOnCheckedChangeListener((buttonView, isChecked) -> + importExportBinding.etPassword.etPassword.setEnabled(isChecked)); + + final AlertDialog[] dialog = new AlertDialog[1]; + final View.OnClickListener onClickListener = v -> { + if (v == passwordParent) importExportBinding.cbPassword.performClick(); + + else if (v == exportLoginsParent) importExportBinding.cbExportLogins.performClick(); + else if (v == exportFavoritesParent) importExportBinding.cbExportFavorites.performClick(); + + else if (v == importLoginsParent) importExportBinding.cbImportLogins.performClick(); + else if (v == importFavoritesParent) importExportBinding.cbImportFavorites.performClick(); + + else if (v == exportSettingsParent) importExportBinding.cbExportSettings.performClick(); + else if (v == importSettingsParent) importExportBinding.cbImportSettings.performClick(); + + else if (context instanceof AppCompatActivity) { + final FragmentManager fragmentManager = ((AppCompatActivity) context).getSupportFragmentManager(); + final String folderPath = settingsHelper.getString(FOLDER_PATH); + + if (v == importExportBinding.btnSaveTo) { + final Editable text = importExportBinding.etPassword.etPassword.getText(); + final boolean passwordChecked = importExportBinding.cbPassword.isChecked(); + if (passwordChecked && isEmpty(text)) + Toast.makeText(context, R.string.dialog_export_err_password_empty, Toast.LENGTH_SHORT).show(); + else { + new DirectoryChooser().setInitialDirectory(folderPath).setInteractionListener(path -> { + final File file = new File(path, "InstaGrabber_Settings_" + System.currentTimeMillis() + ".zaai"); + final String password = passwordChecked ? text.toString() : null; + int flags = 0; + if (importExportBinding.cbExportFavorites.isChecked()) flags |= ExportImportUtils.FLAG_FAVORITES; + if (importExportBinding.cbExportSettings.isChecked()) flags |= ExportImportUtils.FLAG_SETTINGS; + if (importExportBinding.cbExportLogins.isChecked()) flags |= ExportImportUtils.FLAG_COOKIES; + + ExportImportUtils.Export(password, flags, file, result -> { + Toast.makeText(context, result ? R.string.dialog_export_success : R.string.dialog_export_failed, Toast.LENGTH_SHORT).show(); + if (dialog[0] != null && dialog[0].isShowing()) dialog[0].dismiss(); + }); + + }).show(fragmentManager, null); + } + + } else if (v == importExportBinding.btnImport) { + new DirectoryChooser().setInitialDirectory(folderPath).setShowZaAiConfigFiles(true).setInteractionListener(path -> { + int flags = 0; + if (importExportBinding.cbImportFavorites.isChecked()) flags |= ExportImportUtils.FLAG_FAVORITES; + if (importExportBinding.cbImportSettings.isChecked()) flags |= ExportImportUtils.FLAG_SETTINGS; + if (importExportBinding.cbImportLogins.isChecked()) flags |= ExportImportUtils.FLAG_COOKIES; + + ExportImportUtils.Import(context, flags, new File(path), result -> { + ((AppCompatActivity) context).recreate(); + Toast.makeText(context, result ? R.string.dialog_import_success : R.string.dialog_import_failed, Toast.LENGTH_SHORT).show(); + if (dialog[0] != null && dialog[0].isShowing()) dialog[0].dismiss(); + }); + + }).show(fragmentManager, null); + } + } + }; + + passwordParent.setOnClickListener(onClickListener); + exportLoginsParent.setOnClickListener(onClickListener); + exportSettingsParent.setOnClickListener(onClickListener); + exportFavoritesParent.setOnClickListener(onClickListener); + importLoginsParent.setOnClickListener(onClickListener); + importSettingsParent.setOnClickListener(onClickListener); + importFavoritesParent.setOnClickListener(onClickListener); + importExportBinding.btnSaveTo.setOnClickListener(onClickListener); + importExportBinding.btnImport.setOnClickListener(onClickListener); + + dialog[0] = new AlertDialog.Builder(context).setView(importExportBinding.getRoot()).show(); + } + + // taken from Arrays.toString() + @NonNull + public static String highlightIdsMerger(final String... strings) { + if (strings != null) { + int iMax = strings.length - 1; + if (iMax != -1) { + final StringBuilder builder = new StringBuilder(); + builder.append('['); + for (int i = 0; ; i++) { + builder.append('"').append(strings[i]).append('"'); + if (i == iMax) return builder.append(']').toString(); + builder.append(','); + } + } + + } + return "[]"; + } + + public static void putHighlightModels(final HttpURLConnection conn, final Object[] model) throws Exception { + final boolean isHighlightModel = model instanceof HighlightModel[]; + final boolean isFeedStoryModel = model instanceof FeedStoryModel[]; + + if (isHighlightModel || isFeedStoryModel) { + final JSONArray highlightsMediaReel = new JSONObject(Utils.readFromConnection(conn)).getJSONObject("data").getJSONArray("reels_media"); + final int mediaLength = highlightsMediaReel.length(); + + for (int i = 0; i < mediaLength; ++i) { + final JSONArray items = highlightsMediaReel.getJSONObject(i).getJSONArray("items"); + final int itemsLen = items.length(); + + final StoryModel[] storyModels = new StoryModel[itemsLen]; + for (int j = 0; j < itemsLen; ++j) { + final JSONObject data = items.getJSONObject(j); + + final boolean isVideo = data.getBoolean("is_video"); + + boolean hasTappableObjecs = data.has("tappable_objects"); + final JSONArray tappableObjects; + final int tappableLength; + if (hasTappableObjecs) { + tappableObjects = data.getJSONArray("tappable_objects"); + tappableLength = tappableObjects.length(); + hasTappableObjecs = tappableLength > 0; + } else { + tappableLength = 0; + tappableObjects = null; + } + + storyModels[j] = new StoryModel(data.getString(Constants.EXTRAS_ID), data.getString("display_url"), + isVideo ? MediaItemType.MEDIA_TYPE_VIDEO : MediaItemType.MEDIA_TYPE_IMAGE, + data.getLong("taken_at_timestamp")); + + if (isVideo && data.has("video_resources")) + storyModels[j].setVideoUrl(Utils.getHighQualityPost(data.getJSONArray("video_resources"), true)); + + if (hasTappableObjecs) { + for (int k = 0; k < tappableLength; ++k) { + JSONObject jsonObject = tappableObjects.getJSONObject(k); + if (jsonObject.getString("__typename").equals("GraphTappableFeedMedia") && jsonObject.has("media")) { + jsonObject = jsonObject.getJSONObject("media"); + storyModels[j].setTappableShortCode(jsonObject.getString(Constants.EXTRAS_SHORTCODE)); + break; + } + } + } + } + + if (isHighlightModel) + ((HighlightModel[]) model)[i].setStoryModels(storyModels); + else + ((FeedStoryModel[]) model)[i].setStoryModels(storyModels); + } + } + } + + public static CharSequence getSpannableUrl(final String url) { + if (Utils.isEmpty(url)) return url; + final int httpIndex = url.indexOf("http:"); + final int httpsIndex = url.indexOf("https:"); + if (httpIndex == -1 && httpsIndex == -1) return url; + + final int length = url.length(); + + final int startIndex = httpIndex != -1 ? httpIndex : httpsIndex; + final int spaceIndex = url.indexOf(' ', startIndex + 1); + + final int endIndex = (spaceIndex != -1 ? spaceIndex : length); + + final String extractUrl = url.substring(startIndex, Math.min(length, endIndex) - 1); + + final SpannableString spannableString = new SpannableString(url); + spannableString.setSpan(new URLSpan(extractUrl), startIndex, endIndex, 0); + + return spannableString; + } + + public static boolean isEmpty(final CharSequence charSequence) { + if (charSequence == null || charSequence.length() < 1) return true; + if (charSequence instanceof String) { + String str = (String) charSequence; + if ("".equals(str) || "null".equals(str) || str.isEmpty()) return true; + str = str.trim(); + return "".equals(str) || "null".equals(str) || str.isEmpty(); + } + return "null".contentEquals(charSequence) || "".contentEquals(charSequence) || charSequence.length() < 1; + } + + public static boolean isImage(final Uri itemUri, final ContentResolver contentResolver) { + String mimeType; + if (itemUri == null) return false; + final String scheme = itemUri.getScheme(); + if (isEmpty(scheme)) + mimeType = mimeTypeMap.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(itemUri.toString()).toLowerCase()); + else mimeType = scheme.equals(ContentResolver.SCHEME_CONTENT) ? contentResolver.getType(itemUri) + : mimeTypeMap.getMimeTypeFromExtension + (MimeTypeMap.getFileExtensionFromUrl(itemUri.toString()).toLowerCase()); + + if (isEmpty(mimeType)) return true; + mimeType = mimeType.toLowerCase(); + return mimeType.startsWith("image"); + } + + @Nullable + public static String getCookie(@Nullable final String webViewUrl) { + int lastLongestCookieLength = 0; + String mainCookie = null; + + String cookie; + if (!Utils.isEmpty(webViewUrl)) { + cookie = Utils.COOKIE_MANAGER.getCookie(webViewUrl); + if (cookie != null) { + final int cookieLen = cookie.length(); + if (cookieLen > lastLongestCookieLength) { + mainCookie = cookie; + lastLongestCookieLength = cookieLen; + } + } + } + cookie = Utils.COOKIE_MANAGER.getCookie("https://instagram.com"); + if (cookie != null) { + final int cookieLen = cookie.length(); + if (cookieLen > lastLongestCookieLength) { + mainCookie = cookie; + lastLongestCookieLength = cookieLen; + } + } + cookie = Utils.COOKIE_MANAGER.getCookie("https://instagram.com/"); + if (cookie != null) { + final int cookieLen = cookie.length(); + if (cookieLen > lastLongestCookieLength) { + mainCookie = cookie; + lastLongestCookieLength = cookieLen; + } + } + cookie = Utils.COOKIE_MANAGER.getCookie("http://instagram.com"); + if (cookie != null) { + final int cookieLen = cookie.length(); + if (cookieLen > lastLongestCookieLength) { + mainCookie = cookie; + lastLongestCookieLength = cookieLen; + } + } + cookie = Utils.COOKIE_MANAGER.getCookie("http://instagram.com/"); + if (cookie != null) { + final int cookieLen = cookie.length(); + if (cookieLen > lastLongestCookieLength) { + mainCookie = cookie; + lastLongestCookieLength = cookieLen; + } + } + cookie = Utils.COOKIE_MANAGER.getCookie("https://www.instagram.com"); + if (cookie != null) { + final int cookieLen = cookie.length(); + if (cookieLen > lastLongestCookieLength) { + mainCookie = cookie; + lastLongestCookieLength = cookieLen; + } + } + cookie = Utils.COOKIE_MANAGER.getCookie("https://www.instagram.com/"); + if (cookie != null) { + final int cookieLen = cookie.length(); + if (cookieLen > lastLongestCookieLength) { + mainCookie = cookie; + lastLongestCookieLength = cookieLen; + } + } + cookie = Utils.COOKIE_MANAGER.getCookie("http://www.instagram.com"); + if (cookie != null) { + final int cookieLen = cookie.length(); + if (cookieLen > lastLongestCookieLength) { + mainCookie = cookie; + lastLongestCookieLength = cookieLen; + } + } + cookie = Utils.COOKIE_MANAGER.getCookie("http://www.instagram.com/"); + if (cookie != null && cookie.length() > lastLongestCookieLength) mainCookie = cookie; + + return mainCookie; + } + + public static void errorFinish(@NonNull final Activity activity) { + Toast.makeText(activity, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); + activity.finish(); + } + + public static boolean isInstaInstalled(@NonNull final Context context) { + final PackageManager packageManager = context.getPackageManager(); + try { + packageManager.getPackageInfo("com.instagram.android", 0); + return true; + } catch (final Exception e) { + try { + return packageManager.getApplicationInfo("com.instagram.android", 0).enabled; + } catch (final Exception e1) { + return false; + } + } + } + + @Nullable + public static String getInstalledTelegramPackage(@NonNull final Context context) { + final String[] packages = { + "org.telegram.messenger", + "org.thunderdog.challegram", + "ir.ilmili.telegraph", + "org.telegram.BifToGram", + "org.vidogram.messenger", + "com.xplus.messenger", + "com.ellipi.messenger", + "org.telegram.plus", + "com.iMe.android", + "org.viento.colibri", + "org.viento.colibrix", + "ml.parsgram", + "com.ringtoon.app.tl", + }; + + final PackageManager packageManager = context.getPackageManager(); + for (final String pkg : packages) { + try { + final PackageInfo packageInfo = packageManager.getPackageInfo(pkg, 0); + if (packageInfo.applicationInfo.enabled) return pkg; + } catch (final Exception e) { + try { + if (packageManager.getApplicationInfo(pkg, 0).enabled) return pkg; + } catch (final Exception e1) { + // meh + } + } + } + + return null; + } +} \ No newline at end of file diff --git a/app/src/main/java/awaisomereport/CrashReporter.java b/app/src/main/java/awaisomereport/CrashReporter.java new file mode 100755 index 00000000..1884069b --- /dev/null +++ b/app/src/main/java/awaisomereport/CrashReporter.java @@ -0,0 +1,197 @@ +package awaisomereport; + +import android.app.Application; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Process; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.core.content.FileProvider; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.util.Date; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import awais.instagrabber.BuildConfig; +import awais.instagrabber.utils.Utils; + +public final class CrashReporter implements Thread.UncaughtExceptionHandler { + private static CrashReporter reporterInstance; + private final Application application; + private final String email; + private final File crashLogsZip; + private boolean startAttempted = false; + + public static CrashReporter get(final Application application) { + if (reporterInstance == null) reporterInstance = new CrashReporter(application); + return reporterInstance; + } + + private CrashReporter(@NonNull final Application application) { + this.application = application; + // set your email(s) here to receive crash reports + // this.email = ""; + this.email = "chapter50000@hotmail.com"; + this.crashLogsZip = new File(application.getExternalCacheDir(), "crash_logs.zip"); + } + + public void start() { + if (!startAttempted) { + Thread.setDefaultUncaughtExceptionHandler(this); + startAttempted = true; + } + } + + @Override + public void uncaughtException(@NonNull final Thread t, @NonNull final Throwable exception) { + final StringBuilder reportBuilder = new StringBuilder(); + reportBuilder.append("Error report collected on: ").append(new Date().toString()); + reportBuilder.append("\r\n\r\nInformation:\r\n=============="); + + reportBuilder + .append("\r\nVERSION : ").append(BuildConfig.VERSION_NAME) + .append("\r\nVERSION_CODE : ").append(BuildConfig.VERSION_CODE) + .append("\r\nPHONE-MODEL : ").append(Build.MODEL) + .append("\r\nANDROID_VERS : ").append(Build.VERSION.RELEASE) + .append("\r\nANDROID_REL : ").append(Build.VERSION.SDK_INT) + .append("\r\nBRAND : ").append(Build.BRAND) + .append("\r\nMANUFACTURER : ").append(Build.MANUFACTURER) + .append("\r\nBOARD : ").append(Build.BOARD) + .append("\r\nDEVICE : ").append(Build.DEVICE) + .append("\r\nPRODUCT : ").append(Build.PRODUCT) + .append("\r\nHOST : ").append(Build.HOST) + .append("\r\nTAGS : ").append(Build.TAGS); + + reportBuilder.append("\r\n\r\nStack:\r\n==============\r\n"); + final Writer result = new StringWriter(); + try (final PrintWriter printWriter = new PrintWriter(result)) { + exception.printStackTrace(printWriter); + reportBuilder.append(result.toString()); + + reportBuilder.append("\r\nCause:\r\n=============="); + + // for AsyncTask crashes + Throwable cause = exception.getCause(); + while (cause != null) { + cause.printStackTrace(printWriter); + reportBuilder.append(result.toString()); + cause = cause.getCause(); + } + } + reportBuilder.append("\r\n\r\n**** End of current Report ***"); + + final String errorContent = reportBuilder.toString(); + try (final FileOutputStream trace = application.openFileOutput("stack-" + System.currentTimeMillis() + ".stacktrace", Context.MODE_PRIVATE)) { + trace.write(errorContent.getBytes()); + } catch (final Exception ex) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", ex); + } + + application.startActivity(new Intent(application, ErrorReporterActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + + zipLogs(); + + Process.killProcess(Process.myPid()); + System.exit(10); + } + + public synchronized CrashReporter zipLogs() { + final File logDir = Utils.logCollector != null ? Utils.logCollector.getLogDir() : + new File(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? application.getDataDir() : application.getFilesDir(), "ur_mom_gay_logs"); + + try (final FileOutputStream fos = new FileOutputStream(crashLogsZip); + final ZipOutputStream zos = new ZipOutputStream(fos)) { + + final File[] files = logDir.listFiles(); + + if (files != null) { + zos.setLevel(5); + byte[] buffer; + for (final File file : files) { + if (file != null && file.length() > 0) { + buffer = new byte[1024]; + try (final FileInputStream fis = new FileInputStream(file)) { + zos.putNextEntry(new ZipEntry(file.getName())); + int length; + while ((length = fis.read(buffer)) > 0) zos.write(buffer, 0, length); + zos.closeEntry(); + } + } + } + } + + } catch (final Exception e) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + return this; + } + + @SuppressWarnings("ResultOfMethodCallIgnored") + public void startCrashEmailIntent(final Context context, final boolean sendZipsOnly) { + try { + final String filePath = context.getFilesDir().getAbsolutePath(); + + String[] errorFileList; + + if (sendZipsOnly) errorFileList = null; + else { + try { + final File dir = new File(filePath); + if (dir.exists() && !dir.isDirectory()) dir.delete(); + dir.mkdir(); + errorFileList = dir.list((d, name) -> name.endsWith(".stacktrace")); + } catch (final Exception e) { + errorFileList = null; + } + } + + if ((errorFileList != null && errorFileList.length > 0) || sendZipsOnly) { + final StringBuilder errorStringBuilder; + + if (sendZipsOnly) errorStringBuilder = new StringBuilder("So... what happened?\n\n"); + else { + errorStringBuilder = new StringBuilder("\r\n\r\n"); + final int maxSendMail = 5; + + int curIndex = 0; + for (final String curString : errorFileList) { + final File file = new File(filePath + '/' + curString); + + if (curIndex++ <= maxSendMail) { + errorStringBuilder.append("New Trace collected:\r\n=====================\r\n"); + try (final BufferedReader input = new BufferedReader(new FileReader(file))) { + String line; + while ((line = input.readLine()) != null) + errorStringBuilder.append(line).append("\r\n"); + } + } + + file.delete(); + } + + errorStringBuilder.append("\r\n\r\n"); + } + + context.startActivity(Intent.createChooser(new Intent(Intent.ACTION_SEND).setType("message/rfc822") + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION) + .putExtra(Intent.EXTRA_EMAIL, new String[]{email}) + .putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(application, BuildConfig.APPLICATION_ID + ".provider", crashLogsZip)) + .putExtra(Intent.EXTRA_SUBJECT, "InstaGrabber Crash Report") + .putExtra(Intent.EXTRA_TEXT, errorStringBuilder.toString()), "Select an email app to send crash logs")); + } + } catch (final Exception e) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awaisomereport/ErrorReporterActivity.java b/app/src/main/java/awaisomereport/ErrorReporterActivity.java new file mode 100755 index 00000000..5bd4669c --- /dev/null +++ b/app/src/main/java/awaisomereport/ErrorReporterActivity.java @@ -0,0 +1,101 @@ +package awaisomereport; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.style.ImageSpan; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.lang.ref.WeakReference; + +import awais.instagrabber.R; + +public final class ErrorReporterActivity extends Activity implements View.OnClickListener { + private View btnReport; + + @Override + protected void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_crash_error); + + setFinishOnTouchOutside(false); + getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + + final SpannableString crashTitle = new SpannableString(" " + getString(R.string.crash_title)); + crashTitle.setSpan(new CenteredImageSpan(this, android.R.drawable.stat_notify_error), + 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + setTitle(crashTitle); + + btnReport = findViewById(R.id.btnReport); + btnReport.setOnClickListener(this); + findViewById(R.id.btnCancel).setOnClickListener(this); + } + + @Override + public void onClick(@NonNull final View v) { + if (v == btnReport) + CrashReporter.get(getApplication()).startCrashEmailIntent(this, false); + finish(); + System.exit(10); + } + + public static class CenteredImageSpan extends ImageSpan { + private WeakReference drawable; + + public CenteredImageSpan(final Context context, final int drawableRes) { + super(context, drawableRes); + } + + @Override + public int getSize(@NonNull final Paint paint, final CharSequence text, final int start, final int end, @Nullable final Paint.FontMetricsInt fm) { + final Drawable drawable = getCachedDrawable(); + final Rect rect = drawable.getBounds(); + + if (fm != null) { + final Paint.FontMetricsInt pfm = paint.getFontMetricsInt(); + fm.ascent = pfm.ascent; + fm.descent = pfm.descent; + fm.top = pfm.top; + fm.bottom = pfm.bottom; + } + + return rect.right; + } + + @Override + public void draw(@NonNull final Canvas canvas, final CharSequence text, final int start, final int end, final float x, final int top, + final int y, final int bottom, @NonNull final Paint paint) { + final Drawable drawable = getCachedDrawable(); + canvas.save(); + + final int drawableHeight = drawable.getIntrinsicHeight(); + final Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt(); + int transY = bottom - drawable.getBounds().bottom + (drawableHeight - fontMetricsInt.descent + fontMetricsInt.ascent) / 2; + + canvas.translate(x, transY); + drawable.draw(canvas); + canvas.restore(); + } + + private Drawable getCachedDrawable() { + Drawable d = null; + if (drawable != null) d = drawable.get(); + if (d == null) { + d = getDrawable(); + drawable = new WeakReference<>(d); + } + return d; + } + } +} + diff --git a/app/src/main/java/awaisomereport/LogCollector.java b/app/src/main/java/awaisomereport/LogCollector.java new file mode 100755 index 00000000..43ca9596 --- /dev/null +++ b/app/src/main/java/awaisomereport/LogCollector.java @@ -0,0 +1,138 @@ +package awaisomereport; + +import android.app.Application; +import android.os.Build; +import android.util.Log; +import android.util.Pair; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; + +import awais.instagrabber.BuildConfig; + +public final class LogCollector { + private final File logDir; + + public LogCollector(@NonNull final Application app) { + logDir = new File(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? app.getDataDir() : app.getFilesDir(), + "ur_mom_gay_logs"); + + if (logDir.exists()) deleteRecursive(logDir); + + if (logDir.mkdirs()) { + // create log files to zip later + for (final LogFile logFile : LogFile.values()) { + try { + //noinspection ResultOfMethodCallIgnored + new File(logDir, logFile.fileName).createNewFile(); + } catch (final IOException e) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } + } + } + + public File getLogDir() { + return logDir; + } + + @SafeVarargs + public final void appendException(@NonNull final Exception exception, @NonNull final LogFile logFile, @NonNull final String method, + @Nullable final Pair... vars) { + final File excepionFile = new File(logDir, logFile.fileName); + + final StringBuilder stringBuilder = new StringBuilder(); + + stringBuilder.append('\n').append('\n').append("----------------- ").append(method).append(" ------------------") + .append('\n'); + + if (vars != null && vars.length > 0) { + stringBuilder.append("Variables: ").append('\n'); + for (Pair var : vars) + stringBuilder.append('\t').append(var.first).append(" : ") + .append('\u201C').append(var.second).append('\u201D') + .append(" (type: ").append(var.second == null ? "null" : var.second.getClass().getSimpleName()).append(')') + .append('\n'); + stringBuilder.append("----------------------------------").append('\n'); + } + + final Writer stringWriter = new StringWriter(); + try (final PrintWriter printWriter = new PrintWriter(stringWriter)) { + exception.printStackTrace(printWriter); + stringBuilder.append(stringWriter.toString()); + + // for AsyncTask crashes + Throwable cause = exception.getCause(); + while (cause != null) { + cause.printStackTrace(printWriter); + stringBuilder.append(stringWriter.toString()); + cause = cause.getCause(); + } + } + + try (final BufferedReader br = new BufferedReader(new FileReader(excepionFile))) { + String line; + while ((line = br.readLine()) != null) stringBuilder.append(line).append('\n'); + } catch (final Exception e) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + + stringBuilder.append('\n'); + + try (final BufferedWriter bw = new BufferedWriter(new FileWriter(excepionFile))) { + bw.write(stringBuilder.toString()); + } catch (final Exception e) { + if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + } + } + + public enum LogFile { + UTILS("utils.txt"), + MAIN_HELPER("main-helper.txt"), + //////////////////////// + ACTIVITY_STORY_VIEWER("act-story-viewer.txt"), + //////////////////////// + ASYNC_DOWNLOADER("async-download.txt"), + ASYNC_MAIN_POSTS_FETCHER("async-main-posts-fetcher.txt"), + ASYNC_POST_FETCHER("async-single-post-fetcher.txt"), + ASYNC_FEED_FETCHER("async-feed-fetcher.txt"), + ASYNC_PROFILE_FETCHER("async-profile-fetcher.txt"), + ASYNC_PROFILE_PICTURE_FETCHER("async-pfp-fetcher.txt"), + ASYNC_STORY_STATUS_FETCHER("async-story-status-fetcher.txt"), + ASYNC_DISCOVER_FETCHER("async-discover-fetcher.txt"), + ASYNC_COMMENTS_FETCHER("async-comments-fetcher.txt"), + ASYNC_FOLLOW_FETCHER("async-follow-fetcher.txt"), + ASYNC_FEED_STORY_FETCHER("async-feed-story-fetcher.txt"), + //////////////////////// + ASYNC_DMS("async-dms-inbox-fetcher.txt"), + ASYNC_DMS_THREAD("async-dms-thread-fetcher.txt"), + //////////////////////// + DATA_BOX_FAVORITES("data-box-favs.txt"), + UTILS_EXPORT("utils-export.txt"), + UTILS_IMPORT("utils-import.txt"), + ; + private final String fileName; + + LogFile(final String fileName) { + this.fileName = fileName; + } + } + + private static void deleteRecursive(@NonNull final File fileOrDirectory) { + final File[] files; + if (fileOrDirectory.isDirectory() && (files = fileOrDirectory.listFiles()) != null) + for (final File child : files) deleteRecursive(child); + //noinspection ResultOfMethodCallIgnored + fileOrDirectory.delete(); + } +} \ No newline at end of file diff --git a/app/src/main/java/thoughtbot/expandableadapter/ExpandableGroup.java b/app/src/main/java/thoughtbot/expandableadapter/ExpandableGroup.java new file mode 100755 index 00000000..0e499ba8 --- /dev/null +++ b/app/src/main/java/thoughtbot/expandableadapter/ExpandableGroup.java @@ -0,0 +1,40 @@ +package thoughtbot.expandableadapter; + +import java.util.ArrayList; +import java.util.List; + +import awais.instagrabber.models.FollowModel; + +public class ExpandableGroup { + private final String title; + private final List items; + + public ExpandableGroup(final String title, final List items) { + this.title = title; + this.items = items; + } + + public String getTitle() { + return title; + } + + public List getItems(final boolean filtered) { + if (!filtered) return items; + final ArrayList followModels = new ArrayList<>(); + for (final FollowModel followModel : items) if (followModel.isShown()) followModels.add(followModel); + return followModels; + } + + public int getItemCount(final boolean filtered) { + if (items != null) { + final int size = items.size(); + if (filtered) { + int finalSize = 0; + for (int i = 0; i < size; ++i) if (items.get(i).isShown()) ++finalSize; + return finalSize; + } + return size; + } + return 0; + } +} \ No newline at end of file diff --git a/app/src/main/java/thoughtbot/expandableadapter/ExpandableList.java b/app/src/main/java/thoughtbot/expandableadapter/ExpandableList.java new file mode 100755 index 00000000..408e46cf --- /dev/null +++ b/app/src/main/java/thoughtbot/expandableadapter/ExpandableList.java @@ -0,0 +1,51 @@ +package thoughtbot.expandableadapter; + +import androidx.annotation.NonNull; + +import java.util.ArrayList; + +public final class ExpandableList { + private final int groupsSize; + public final ArrayList groups; + public final boolean[] expandedGroupIndexes; + + public ExpandableList(@NonNull final ArrayList groups) { + this.groups = groups; + this.groupsSize = groups.size(); + this.expandedGroupIndexes = new boolean[groupsSize]; + } + + public int getVisibleItemCount() { + int count = 0; + for (int i = 0; i < groupsSize; i++) count = count + numberOfVisibleItemsInGroup(i); + return count; + } + + @NonNull + public ExpandableListPosition getUnflattenedPosition(final int flPos) { + int adapted = flPos; + for (int i = 0; i < groupsSize; i++) { + final int groupItemCount = numberOfVisibleItemsInGroup(i); + if (adapted == 0) + return ExpandableListPosition.obtain(ExpandableListPosition.GROUP, i, -1, flPos); + else if (adapted < groupItemCount) + return ExpandableListPosition.obtain(ExpandableListPosition.CHILD, i, adapted - 1, flPos); + adapted = adapted - groupItemCount; + } + throw new RuntimeException("Unknown state"); + } + + private int numberOfVisibleItemsInGroup(final int group) { + return expandedGroupIndexes[group] ? groups.get(group).getItemCount(true) + 1 : 1; + } + + public int getFlattenedGroupIndex(@NonNull final ExpandableListPosition listPosition) { + int runningTotal = 0; + for (int i = 0; i < listPosition.groupPos; i++) runningTotal = runningTotal + numberOfVisibleItemsInGroup(i); + return runningTotal; + } + + public ExpandableGroup getExpandableGroup(@NonNull ExpandableListPosition listPosition) { + return groups.get(listPosition.groupPos); + } +} \ No newline at end of file diff --git a/app/src/main/java/thoughtbot/expandableadapter/ExpandableListPosition.java b/app/src/main/java/thoughtbot/expandableadapter/ExpandableListPosition.java new file mode 100755 index 00000000..3a2e33ef --- /dev/null +++ b/app/src/main/java/thoughtbot/expandableadapter/ExpandableListPosition.java @@ -0,0 +1,41 @@ +package thoughtbot.expandableadapter; + +import androidx.annotation.NonNull; + +public class ExpandableListPosition { + private static final ExpandableListPosition LIST_POSITION = new ExpandableListPosition(); + public final static int CHILD = 1; + public final static int GROUP = 2; + private int flatListPos; + public int groupPos; + public int childPos; + public int type; + + @NonNull + public static ExpandableListPosition obtain(final int type, final int groupPos, final int childPos, final int flatListPos) { + LIST_POSITION.type = type; + LIST_POSITION.groupPos = groupPos; + LIST_POSITION.childPos = childPos; + LIST_POSITION.flatListPos = flatListPos; + return LIST_POSITION; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + //if (o != null && getClass() == o.getClass()) { + if (o instanceof ExpandableListPosition) { + final ExpandableListPosition that = (ExpandableListPosition) o; + if (groupPos != that.groupPos) return false; + if (childPos != that.childPos) return false; + if (flatListPos != that.flatListPos) return false; + return type == that.type; + } + return false; + } + + @Override + public int hashCode() { + return 31 * (31 * (31 * groupPos + childPos) + flatListPos) + type; + } +} \ No newline at end of file diff --git a/app/src/main/java/thoughtbot/expandableadapter/GroupViewHolder.java b/app/src/main/java/thoughtbot/expandableadapter/GroupViewHolder.java new file mode 100755 index 00000000..075174b6 --- /dev/null +++ b/app/src/main/java/thoughtbot/expandableadapter/GroupViewHolder.java @@ -0,0 +1,39 @@ +package thoughtbot.expandableadapter; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import awais.instagrabber.R; +import awais.instagrabber.interfaces.OnGroupClickListener; + +public class GroupViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + private final OnGroupClickListener listener; + private final TextView title; + private final ImageView arrow; + + public GroupViewHolder(@NonNull final View itemView, final OnGroupClickListener listener) { + super(itemView); + this.listener = listener; + this.title = itemView.findViewById(android.R.id.text1); + this.arrow = itemView.findViewById(R.id.collapsingArrow); + this.title.setBackgroundColor(0x80_1565C0); + itemView.setOnClickListener(this); + } + + public void setTitle(@NonNull final String title) { + this.title.setText(title); + } + + @Override + public void onClick(final View v) { + if (listener != null) listener.toggleGroup(getLayoutPosition()); + } + + public void toggle(final boolean expand) { + arrow.setImageResource(expand ? R.drawable.collapse : R.drawable.expand); + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/ic_download.png~ b/app/src/main/res/drawable-hdpi/ic_download.png~ new file mode 100755 index 0000000000000000000000000000000000000000..a81ad20066b73901e8cded7ce5c9e899766e5b63 GIT binary patch literal 1070 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}trX+877l!}s{b%+Ad7K3vk;OpT z1B~5HX4`=T%L*LRfizez!?|}o;S3DSW}YsNArXh)PCxB05-D7Up|DORP&j<^C&9;ucuplWNaSw0 zxJ*9eZgtFpfTgjqriXkYKIm#)tPVn3-H*S7tO7i2j2zo0y_+FM)wt5ep* z*jGF1p4*kZKFy=J&1U`}aKY>0hWc0id&LW;Tt3<^yZhNI`S2NPUYZPT6Xw=>Pp^~wqno_oNyRt6 zvar8Dj5sbS2rOpDz%W%td%ylZJEdCnYT(BpX>Ve_)j@5_`m z3!9oA);-%CT)F;IjknrTD@KPXO}_PWe(ueWnSH)n)Wy%Lf6wxrjWeTUITN$EFI?HQ zJpJRNsm<3nCtZ!I<t}_QUBN9 z@@l(iDje2R2{KF&xvZP{z@y1@<89T-4T-s`4K4FtPAz-E9sXH|#f39?@}hITzc`573>}(%N3V zHL$QUFj(SObP`2FZhlH;S|x4`SA|cN0yRj2YzWRzD=AMbN@Z|N$xljE@XSq2PYp^< WOsOn9nQ8-6#Ng@b=d#Wzp$P!BnbL0n literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/nav_up.png b/app/src/main/res/drawable-hdpi/nav_up.png new file mode 100755 index 0000000000000000000000000000000000000000..99622e7cf0778b50bac047f1b056598dd4ac17eb GIT binary patch literal 302 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhawzIwVihEy=Vy=3Xf>>$8;(Tagl zG48;O;!S6CBYA(QsO2?Yo#d??`6&FGyYQX`j2@axrwBC{#?4`7KNeXilF4*@vRZ)+ zh_X38Ijz{{WU&qB`HxF}%J_ehDNC)jn)JM;Aog3YY9-%OR)3>8rhk|Yx=mntKG*aQ zXA^IHlZs`?1O?4=Tzw6G3X$iewKE(GPMgnjIUni7ETnQW(_!9~f;b?1lFIp)4jXKp zF3n;6vY>JaS5+dTdUL|*eSfN%9JS`iU70L*SJbwcl`F)Pzr*dRhQOVT&*g5iS_HhD qB*`hj$SM-x042Wc_Xc{Pj=@k4UOiAAEE)4(M`_JqL@;D1TB8!2v z2N=7Z%(epwmK8Xr18D^?ZvQoBE>N4Ir;B5V$ML6A_GbqNiX69pzVG^xHt{t}%``@Bz z^u93jh8Af}WVUv(7G?)6w<*nDOW3tL1;pd~zhQVZoeN zyN$ywlGjSKEaTbn@Za>A8=vw%U+At~p~JmB{g~QX(fs@A?t;^+w;j)ld*#l+v&*0; z^;h059n`Dny6cZ~kL(tj^6y^IXO|ax@fEgnG7rs)|FdcHtWUnB z;ruv!#|p`>5#_tO zO=n%(yKUN|WE;XL|(#mD6+pvJe`TP30huyrkEPwd+wpf+fRkrWb z!pzfGD!*{#o_X=k=Z3V~3!>PvbJYH&m(Vtmvn% zTsPKEL+yDRo literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-night-hdpi/nav_up.png b/app/src/main/res/drawable-night-hdpi/nav_up.png new file mode 100755 index 0000000000000000000000000000000000000000..d7b27da82ec7793d6f4e24fdd3e321e6af0ffd25 GIT binary patch literal 319 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXoKNz{uw5;uuoF`1XpsADf{>bE13$ zt9O;PdTQR!%ZYwTU*0x#h^THma%{c+2M^5^L0+0mkMv4Elz4ID*eRz?g)u6^$K5v- z%uz9RS3fCZ?)l`0r_ynMA%&t2q~ObWADe^j#RfOOsY$zc}hM;KHlfMuUq=pU7A zaG7*Yvhl!e$xA%Xr${ubTw-~#)8h03rMEfNm-^ONOmNum*?()P-G`O{N8Xo?Ro{5s zSsTmmRIabzopr0I`LC!~g&Q literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-night-mdpi/nav_up.png b/app/src/main/res/drawable-night-mdpi/nav_up.png new file mode 100755 index 0000000000000000000000000000000000000000..edd9b1ddfbfc08f9d374ec2ccc69dbedc56f352f GIT binary patch literal 217 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}b0D1)eUBAr*{oFFSG_3gBUTSibtz z(IdStCSK)U!T3{A!Dw^Hq@1|Snfy_^($do2*yyc~O*?yd>iWQz^WKM^t3LcZ=|iRG zk3A|r|7Kn86;|8-bWh=-C*kYF)Lr&5&Uo;X@5(!l#?P`3Sk9L-2rJ!heDlxx;Ahzb zN75B4Swsr!?^|9DpJK!4H0Oo8of?0G0Q-OSVg>6149q+qemj&kF#hAJU@}d}o}j7} RtqpW5gQu&X%Q~loCIA@?R-pg@ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-night-xhdpi/nav_up.png b/app/src/main/res/drawable-night-xhdpi/nav_up.png new file mode 100755 index 0000000000000000000000000000000000000000..8ac0552c7a37489e82306723c6c814da946ec028 GIT binary patch literal 354 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD0wg^q?%&M7z^Liz;uuoF`1aaa-@^eSY=Pne zRV{WL7o_cTCEv(a#b^du?Ed-gTz5v_lm_$7*P^o5ZoL+D`+i;CWOe&LC+yug?c{}P z?9_hL_#F5-ui>*T*0_-XuLNBe)3hCiGM918VJ5=$Qg2Y~_#?SN z$nL!=kY?aes%K+pIx(NILE%$6g92D+JM*(YzZs1mhSsz``*WMY_+j?{z2YC0?LIRm zsKy+ff6-W;A?#4-A7yKhfK7LJ=W^xw%zTFy*UbIa@RNy!LqNfyfq@a3@jxG0R Ysd2aV@GU$l0}ML`Pgg&ebxsLQ0Maao1poj5 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-night-xxhdpi/nav_up.png b/app/src/main/res/drawable-night-xxhdpi/nav_up.png new file mode 100755 index 0000000000000000000000000000000000000000..5e61c3d18dacd80e410b098b0fa092c4be3bc862 GIT binary patch literal 506 zcmeAS@N?(olHy`uVBq!ia0vp^6F``S8Ays|{O<-*>H$6>u0Z-f5n!FImnBdsZ%L3} zFhc{w|BA}0>iU|xS{t6#{2v(@7)w1}978G?-(ETEnd2zp`tWPe1rD76!8s@PGS{b> zvpO5F7#pyhJs`ky@Whh%LWd*owzfOXw_SPj(d+qIReR&sU$@@$*ILr9?fn-uo|EUM zsVWFI0EvkWLPDGxih_+yLV_9!4;S>bG#d%=o$|2IP=<1tx;!~F)D#!YXlY0iLgz?i z%ssw%qQM2T{$l0C1%~GnRd_-afh;abPUg@P9ug~@+zvU28VRwjngCR_{lZa2AoD_= zKRcRKKxwLs>=Tc711I#H#ehVO6Nc6g!E-COS37xrDKi2nEf=)N~+ zox)G&egF1({b8rcU-IftoCQ(|;VH6WvzGAh-ZHyY?d7?76H6m9CdH|m*loVBb^lGd vRi!JOWnTrfTU}Ym2V}a7!v(&4caEP}bIR)2W1&=F%rJPm`njxgN@xNAb2i$s literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-night/collapse.png b/app/src/main/res/drawable-night/collapse.png new file mode 100755 index 0000000000000000000000000000000000000000..933450eb4516939d71097b8efcdf752f2cb93eaa GIT binary patch literal 3457 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-night/comments.png b/app/src/main/res/drawable-night/comments.png new file mode 100755 index 0000000000000000000000000000000000000000..5693f09727e631dc9e4ab98f7acfed4e4fa4d62d GIT binary patch literal 9189 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

U)?2}bXG~~cFZ(`;e5vTLC-NCBUwo# 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 P@1Q8jsX^*w%)|db4&iUk literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-night/expand.png b/app/src/main/res/drawable-night/expand.png new file mode 100755 index 0000000000000000000000000000000000000000..4e0a2e6209ccbb0da30e0c6c83072651f2dd61cc GIT binary patch literal 3510 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-night/mute.png b/app/src/main/res/drawable-night/mute.png new file mode 100755 index 0000000000000000000000000000000000000000..734108c926876fe7447e705aa3cdde1d433400a6 GIT binary patch literal 7877 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 KQK?t5jr||~E1IkT literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-night/video_views.png b/app/src/main/res/drawable-night/video_views.png new file mode 100755 index 0000000000000000000000000000000000000000..8922fa8a6628ad1d66fd79a868ba394c768a5e8b GIT binary patch literal 11908 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 V4#tpVPyfTtLGo&H)iUN`{{@nHrS<>- literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-night/vol.png b/app/src/main/res/drawable-night/vol.png new file mode 100755 index 0000000000000000000000000000000000000000..abd10560c05e064d0fd553a2ad08fcb7ab3f8b83 GIT binary patch literal 8473 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 JS?83{1OVokc%c9Q literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/nav_up.png b/app/src/main/res/drawable-xxhdpi/nav_up.png new file mode 100755 index 0000000000000000000000000000000000000000..f5299450b8f473519dfe1de8177e6d45f6771643 GIT binary patch literal 448 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 IWX;0<7fokwVgLXD literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/collapse.png b/app/src/main/res/drawable/collapse.png new file mode 100755 index 0000000000000000000000000000000000000000..711da4404fa4682597d04d5d87f794e46ab89d0c GIT binary patch literal 2760 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 K;x(d1LH`3vi8lfO literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/expand.png b/app/src/main/res/drawable/expand.png new file mode 100755 index 0000000000000000000000000000000000000000..97f0359f0f63cfe8443b8beafcc4449c9df52a00 GIT binary patch literal 2813 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 P00000NkvXXu0mjfQOZH< literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/expired.png b/app/src/main/res/drawable/expired.png new file mode 100755 index 0000000000000000000000000000000000000000..7fe4872617efb94c41ec3dc95f618066f017c3c0 GIT binary patch literal 5491 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 + + diff --git a/app/src/main/res/drawable/ic_discover.xml b/app/src/main/res/drawable/ic_discover.xml new file mode 100755 index 00000000..7a1ab400 --- /dev/null +++ b/app/src/main/res/drawable/ic_discover.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_download.xml b/app/src/main/res/drawable/ic_download.xml new file mode 100755 index 00000000..3fb23459 --- /dev/null +++ b/app/src/main/res/drawable/ic_download.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_feed.xml b/app/src/main/res/drawable/ic_feed.xml new file mode 100755 index 00000000..c163a23d --- /dev/null +++ b/app/src/main/res/drawable/ic_feed.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_fullscreen.xml b/app/src/main/res/drawable/ic_fullscreen.xml new file mode 100755 index 00000000..fefb27a3 --- /dev/null +++ b/app/src/main/res/drawable/ic_fullscreen.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_fullscreen_exit.xml b/app/src/main/res/drawable/ic_fullscreen_exit.xml new file mode 100755 index 00000000..ad756976 --- /dev/null +++ b/app/src/main/res/drawable/ic_fullscreen_exit.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_import_export.xml b/app/src/main/res/drawable/ic_import_export.xml new file mode 100755 index 00000000..2249979f --- /dev/null +++ b/app/src/main/res/drawable/ic_import_export.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_profile.xml b/app/src/main/res/drawable/ic_profile.xml new file mode 100755 index 00000000..568656a1 --- /dev/null +++ b/app/src/main/res/drawable/ic_profile.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/lock.xml b/app/src/main/res/drawable/lock.xml new file mode 100755 index 00000000..4bb23a77 --- /dev/null +++ b/app/src/main/res/drawable/lock.xml @@ -0,0 +1,12 @@ + + + diff --git a/app/src/main/res/drawable/mute.png b/app/src/main/res/drawable/mute.png new file mode 100755 index 0000000000000000000000000000000000000000..fe29c59b80df3802f7c7bb50c68e25bf411b6e83 GIT binary patch literal 6263 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/slider.png b/app/src/main/res/drawable/slider.png new file mode 100755 index 0000000000000000000000000000000000000000..d05ba141c9a56cc295a0f90d4a7a78a9504a4173 GIT binary patch literal 3371 zcmai1c`)1i7WY(%rIuK#tr8Kt(w5qaD{hcqY!$?=wbxQh)U{KoT3;)Ppw!YLTzkb* zYU%AQE>TTU6c@FNom!)Kxo_S-Z{B#T&2&uXo{cWE4nZ#6eZi%ZxKDts zoA3_l^9UY}7vNzEcriV=wV*5B!yTKDaQ#{|-!L~3p_TnX_Ob8lcbRJOjhu6-uB^w= zcPmp1WGp`|yq4`K$jfUB@$i_hLy>nLp;yGK_ud$md~^y>Y}9=AQ~KQD%8wsEj<_!> zxBaraJmB|?CuM0mz*lsNy5C25;DA7t|F%$GUQTeR-uHGlozyQYpKcDGtF7%|tb`fP zJ3?>DLEohGmuU}btg zfBt-~`+3L`t+1B8yUw!MMb5|CJoYqoumV&0)X;KQYSAq=CqG|TLrrbhM4-IP6En%s zY(mw3rn`bYuF_x0%E}&Wj5n^5^RnXblm`<{=eW7Kmy})F!mUO+c1y0y6O({usIHNb zk$4}R&T&o5$=KLfqKSd8x)^*cFx};pySqn4ms^Y9+Yo*{*%~%osJ^Q&@|8InAWEW1t!& zZ8BoXwdc2QtyEPjpkiu5F%FknLPr!Fp+aTp-STr!Wr5Cm8U(3n_|lG)zsoNx4HK4` zsMRUdh_}80qA(mlLU;KEm$kqqU_rTlCri_J+y+>o7pdN2lUK?p_4fO3uSv~>I?AZ{ z5SNbOFYP#s@_=dtLP87cku>slf1`C18*Gb`rBKR6+mBDTH}fLq3C1#Fz{+6wQM7ILuk#xQl2$e0qV5>~ z4Lvexsw3w3Ks<8!l}2f4sd=x4hMnh&m|~k{RJ83P$7=q)57-8Z1p?vcJpL~3Y)B&R z$M$z9rAt6MoA}U*f3S!{utb=!zc!|-&1{KIb{M^t4W1=#LNcNxC;u6>+5Rqeqh*O# zn|K)T`%cO$h8h2|Du5!Rk9uVbf7qnS4>oo^1F<^Otq_Qf=DBB^h1#JjHP-mgfkt(G zRnN+h1#GWAuBejGD~H>2eA-wwg?jA*sK5udNsrB`_9QfXjr+;i`7ZyN;;bzNSGM>m z&!C{7z+CYr(Xo^DUs5uAsK-cz_G=6`{ADE%56_zE`MR$AUrNFdJh=~h&O59UtJ-SY z2OhLSuXfx^hTu7(u|co+Azj&`ErIQPgBb0$1J!8l6c z797ien*a3ti}hdG|2+F2SN?|^$MWxykZGcc#Tu3=1Q4eqNnrrsKk zUnCD#q%SQk(NyD475PKutEX;b?tW0fWg+@z^}lx=h{^YZdS z__h1`k)VboSRkhxqEqMeaPI7Qxi~#m*-4^T+RDm`2urc$FO-8Jk1y~0oA8QhZl&ks zJC)g}vWhi?t8kTd_G> ztEXXl2U1}qyHyKbN8UOZfPm>eT>kvR`%~W0%-Y(T*325l7Co0?p-14;JJe?mWW|&s zWRV;ZUEc6R6x^kI;@Da0yztFi(Qk;3LA{Ziq(Z^E-#@BOU%GlVCj4My@*r@cX}v}+ zHDJ^sJEwbH*v-cWs2HyJ*x%pFjK4FcP`yWC%aOAb0$QA0w(qA6p)86>kp_qk5rXgA z$p*bs2ZV^B2M}=W=ZZ28>YBd73;V>%ydFB&Y=(!ukavio!n=d1s52pf8;Sd#&gbUD zj@Acz&ADvxc(H(T8yLJu`9PdnuM%96Qk_2OH5GeGd6+a<;b4P-Er+Sx)%KJ89eq}9)fzj zYTuj0q&0jw*x9qX^zlzKZL5)PWya;!J2f<4NnO)#1UAk#OJF<=_BS}#B9i&WFRa{- zA_a~IvObK4R0XevNSTlXC9S_bMY8tJa1rh9Rw`zu+VUWLl#S|zw#h&-cS8T5)U&y_ z3AW*BYW63S7P?3&fFzX^4u&0zQ_cBH?BY^}O~H;?UWySv`=F~aOZksqhIi+JD^p(M>6V??&|tu?7CtfweVv`1N%7bmHhXWP+>#b5z*z?kEn3-Q5J$%ER|DzlWF%5( z`qXHeHWUYAZpC(gPVo3;PIu-6v?Uq^;$jjjm7$C@m5$_#A|j`aAxobmAU)k|oMb@G zbp)D}+>@zjdm6Jn+eN!3F#AZTGy^RJ$9oZ#4z6I7R(CHvn~q$qp1ykfmo?C8gSv5n z*NLGbR!K=I`s9n1#mTiRs^0aUH_SZ7{yYn_?3R74lF{k%#zurdou8ji-|RTvSjrh+ zHz7Wa{-k@@zV$nIoK6g5*R!SZlP^4=x`jI8?kS^qISWid>?1sC$dz@DAZ07{MlaG_wTPLS@QGUD^3IZGTt=Rn5 z1Q8Y(!_o)Ib4h#>r)ENi=S+_`KpxpPDjkQjh318NCxs6ORme~!O`?(}-7;i;`8kA) zOV8jWIgi}}pX~IhSlCn!zu9cv>~LllEQ)F0^*hs+`*2xAJd%canx1|)a(BS^?7F)8 z{#}!2(u#&6`7yUl{$3?}V{oRDZdjnC@Hwqn{w4(Ki16s^&5$)V&(qxgwzai2^Zxz& znfUnliG~qrq5CSqVxyJAD?gY$P-|vt8XeBuYJK#vimxluPFf;)6yE`2$p#6-iEB7z z#DqyHPwQlI%}ywcgg`3?Y%xcRt5Gi_a*qQF%~^3uTIhuNAewI|0{?3gd$)6^XqjNU z%&Fqm{v%J^*Dy6`&mz~XVtp1X8a7DwleFaHN!>L6;D4P|pTmwNDKR@)*sbd9k>|VV zy1kB3CBWBwlb~CcnU)Bmbi)Cilaz3@%x$8lbWUmK3KI8K-Yv~7+q!@L8;Ze>MpVgs z3Nv<7zeA8tu5E+D$6r7Kau%{2LzhCHQWe1-kBwi$wjvJXFgu_k9ULCw7j+hc6Sa?^ zs_%m=v%CE$2)R0S5>yh1HomzI@D3KM$`gB5LT&5R?siRV!|07{oB*-CcUL$_ky)mdt>Hv0^qun;PPT6L#IIFcv7&H!&lLa-M7`be~AKpZg5 zK={B6m19pVRQTF_x4t5|hP^kf%Fu|C#^e6hg3BjrTNQ?`2DB&r7Nk24&)dvi#tM)L zJjnz0mbucrxcP5qmEnQfn1Ea3fvGoL8TKMQN&2SXDL#+?`wL(aULXDhzFkH8uxaG^ O7acG(N7NYH!~FvxPaxF* literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/verified.png b/app/src/main/res/drawable/verified.png new file mode 100755 index 0000000000000000000000000000000000000000..8e523b122a2bff2e2dd904c4f93e30e20d603df0 GIT binary patch literal 6450 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 K^5wE-q5lGncVRgI literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/video.png b/app/src/main/res/drawable/video.png new file mode 100755 index 0000000000000000000000000000000000000000..e088392a0b04c092aee79b88a1ca21e24e5cdf91 GIT binary patch literal 6913 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/video_views.png b/app/src/main/res/drawable/video_views.png new file mode 100755 index 0000000000000000000000000000000000000000..e3ed5af734a4574ddd76d6cb444e5f5a82bf33e7 GIT binary patch literal 6672 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 a9nNRBPO>zyRsDa4s}MCE)oNvU*na?!rH4-d literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/vol.png b/app/src/main/res/drawable/vol.png new file mode 100755 index 0000000000000000000000000000000000000000..036402bac12f4d5c9f93ff75f43bf8c62a1b211a GIT binary patch literal 6708 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

7fzUNY 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́!UI3!iJ@TEpi2?zV>&#foE4huBD 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

Z$(#6T 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 WLJY1pVb~Txe{N{#see$je)>OVwKd`Z literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/zzz_ms.png b/app/src/main/res/drawable/zzz_ms.png new file mode 100755 index 0000000000000000000000000000000000000000..fad973f5e12104403ba249ddadcafb42c9765b6f GIT binary patch literal 72460 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

_~s^XFDq|+82i1#|06@ixvJ2E(TMfUa9saA~~ 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

L};nwthAcSv!%AcDSt&cErm5tG{tsSNgXe%(p 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 Blm)z%7RRo{AwG7a?T8Ox$ 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

|C=lx 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/zzz_rev.png b/app/src/main/res/drawable/zzz_rev.png new file mode 100755 index 0000000000000000000000000000000000000000..c377a5f709199cd129deafd02b5f0a5071ae837d GIT binary patch literal 47209 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 D;yCVV literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/zzz_revl.png b/app/src/main/res/drawable/zzz_revl.png new file mode 100755 index 0000000000000000000000000000000000000000..195247654475040bccf872ced7fd600e4acd5ae1 GIT binary patch literal 66969 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/zzz_tesv.png b/app/src/main/res/drawable/zzz_tesv.png new file mode 100755 index 0000000000000000000000000000000000000000..abd957753672f927f6135f995b14ae4b0b17b6f4 GIT binary patch literal 30593 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 E0B=7t3IG5A literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/activity_comments.xml b/app/src/main/res/layout/activity_comments.xml new file mode 100755 index 00000000..7bad2d17 --- /dev/null +++ b/app/src/main/res/layout/activity_comments.xml @@ -0,0 +1,25 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_crash_error.xml b/app/src/main/res/layout/activity_crash_error.xml new file mode 100755 index 00000000..5c919d36 --- /dev/null +++ b/app/src/main/res/layout/activity_crash_error.xml @@ -0,0 +1,55 @@ + + + + + + + +