From 456429725b4ec70024d53cdbc7faa9889d1c97ff Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Sun, 29 Sep 2019 21:18:45 +0800 Subject: Change project structures. --- app/src/main/AndroidManifest.xml | 102 +- .../infinityforreddit/AccountPostsActivity.java | 290 ---- .../AccountRecyclerViewAdapter.java | 129 -- .../AccountSavedThingActivity.java | 402 ----- .../Activity/AccountPostsActivity.java | 305 ++++ .../Activity/AccountSavedThingActivity.java | 417 +++++ .../Activity/CommentActivity.java | 284 ++++ .../Activity/EditCommentActivity.java | 217 +++ .../Activity/EditPostActivity.java | 207 +++ .../Activity/FilteredThingActivity.java | 402 +++++ .../Activity/LinkResolverActivity.java | 215 +++ .../infinityforreddit/Activity/LoginActivity.java | 232 +++ .../infinityforreddit/Activity/MainActivity.java | 1247 ++++++++++++++ .../Activity/PostImageActivity.java | 600 +++++++ .../Activity/PostLinkActivity.java | 510 ++++++ .../Activity/PostTextActivity.java | 510 ++++++ .../Activity/PostVideoActivity.java | 634 +++++++ .../infinityforreddit/Activity/RulesActivity.java | 292 ++++ .../infinityforreddit/Activity/SearchActivity.java | 305 ++++ .../Activity/SearchResultActivity.java | 412 +++++ .../Activity/SearchSubredditsResultActivity.java | 229 +++ .../Activity/SettingsActivity.java | 154 ++ .../Activity/ShareDataResolverActivity.java | 83 + .../Activity/SubredditSelectionActivity.java | 323 ++++ .../Activity/SubscribedThingListingActivity.java | 317 ++++ .../Activity/ViewImageActivity.java | 468 ++++++ .../Activity/ViewMessageActivity.java | 333 ++++ .../Activity/ViewPostDetailActivity.java | 1320 +++++++++++++++ .../Activity/ViewSubredditDetailActivity.java | 676 ++++++++ .../Activity/ViewUserDetailActivity.java | 800 +++++++++ .../Activity/ViewVideoActivity.java | 369 ++++ .../Adapter/AccountRecyclerViewAdapter.java | 130 ++ .../Adapter/CommentAndPostRecyclerViewAdapter.java | 1772 ++++++++++++++++++++ .../CommentsListingRecyclerViewAdapter.java | 438 +++++ .../FlairBottomSheetRecyclerViewAdapter.java | 107 ++ .../Adapter/FollowedUsersRecyclerViewAdapter.java | 91 + .../Adapter/MessageRecyclerViewAdapter.java | 250 +++ .../Adapter/PostRecyclerViewAdapter.java | 878 ++++++++++ .../Adapter/RulesRecyclerViewAdapter.java | 95 ++ .../SubredditListingRecyclerViewAdapter.java | 231 +++ .../SubscribedSubredditsRecyclerViewAdapter.java | 154 ++ .../Adapter/UserListingRecyclerViewAdapter.java | 234 +++ .../AppBarStateChangeListener.java | 4 +- .../infinityforreddit/AppComponent.java | 32 + .../AsyncTask/CheckIsFollowingUserAsyncTask.java | 43 + .../CheckIsSubscribedToSubredditAsyncTask.java | 45 + .../AsyncTask/GetCurrentAccountAsyncTask.java | 33 + .../AsyncTask/InsertSubscribedThingsAsyncTask.java | 80 + .../AsyncTask/InsertUserDataAsyncTask.java | 36 + .../AsyncTask/LoadSubredditIconAsyncTask.java | 72 + .../AsyncTask/LoadUserDataAsyncTask.java | 59 + .../ParseAndInsertNewAccountAsyncTask.java | 51 + .../AsyncTask/SwitchAccountAsyncTask.java | 37 + .../SwitchToAnonymousAccountAsyncTask.java | 38 + .../infinityforreddit/ChangeFontSizeEvent.java | 3 - .../infinityforreddit/ChangeNSFWBlurEvent.java | 8 - .../infinityforreddit/ChangeNSFWEvent.java | 8 - .../infinityforreddit/ChangeSpoilerBlurEvent.java | 8 - .../CheckIsFollowingUserAsyncTask.java | 43 - .../CheckIsSubscribedToSubredditAsyncTask.java | 44 - .../infinityforreddit/CommentActivity.java | 273 --- .../CommentAndPostRecyclerViewAdapter.java | 1752 ------------------- .../infinityforreddit/CommentData.java | 12 +- .../infinityforreddit/CommentViewModel.java | 14 +- .../infinityforreddit/CommentsListingFragment.java | 216 --- .../CommentsListingRecyclerViewAdapter.java | 427 ----- .../infinityforreddit/DeleteThing.java | 6 +- .../infinityforreddit/EditCommentActivity.java | 208 --- .../infinityforreddit/EditPostActivity.java | 198 --- .../Event/ChangeFontSizeEvent.java | 3 + .../Event/ChangeNSFWBlurEvent.java | 8 + .../infinityforreddit/Event/ChangeNSFWEvent.java | 8 + .../Event/ChangeSpoilerBlurEvent.java | 8 + .../Event/PostUpdateEventToDetailActivity.java | 11 + .../Event/PostUpdateEventToPostList.java | 13 + .../Event/SubmitImagePostEvent.java | 11 + .../Event/SubmitTextOrLinkPostEvent.java | 15 + .../Event/SubmitVideoPostEvent.java | 13 + .../Event/SwitchAccountEvent.java | 9 + .../infinityforreddit/FetchComment.java | 16 +- .../infinityforreddit/FetchFlairs.java | 6 +- .../infinityforreddit/FetchMessages.java | 10 +- .../infinityforreddit/FetchMyInfo.java | 8 +- .../infinityforreddit/FetchPost.java | 6 +- .../infinityforreddit/FetchSubredditData.java | 6 +- .../infinityforreddit/FetchSubscribedThing.java | 14 +- .../infinityforreddit/FilteredThingActivity.java | 385 ----- .../docilealligator/infinityforreddit/Flair.java | 2 +- .../FlairBottomSheetFragment.java | 120 -- .../FlairBottomSheetRecyclerViewAdapter.java | 105 -- .../FollowedUsersListingFragment.java | 100 -- .../FollowedUsersRecyclerViewAdapter.java | 89 - .../Fragment/CommentsListingFragment.java | 225 +++ .../Fragment/FlairBottomSheetFragment.java | 125 ++ .../Fragment/FollowedUsersListingFragment.java | 104 ++ .../Fragment/ModifyCommentBottomSheetFragment.java | 88 + .../infinityforreddit/Fragment/PostFragment.java | 683 ++++++++ .../Fragment/PostTypeBottomSheetFragment.java | 82 + .../SearchPostSortTypeBottomSheetFragment.java | 84 + ...serAndSubredditSortTypeBottomSheetFragment.java | 70 + .../Fragment/SortTypeBottomSheetFragment.java | 103 ++ .../Fragment/SubredditListingFragment.java | 190 +++ .../SubscribedSubredditsListingFragment.java | 121 ++ .../Fragment/UserListingFragment.java | 167 ++ .../UserThingSortTypeBottomSheetFragment.java | 90 + .../infinityforreddit/FragmentCommunicator.java | 2 +- .../GetCurrentAccountAsyncTask.java | 33 - .../infinityforreddit/HidePost.java | 12 +- .../InsertSubscribedThingsAsyncTask.java | 79 - .../infinityforreddit/InsertUserDataAsyncTask.java | 36 - .../infinityforreddit/JSONUtils.java | 160 +- .../infinityforreddit/LinkResolverActivity.java | 211 --- .../LoadSubredditIconAsyncTask.java | 70 - .../infinityforreddit/LoadUserDataAsyncTask.java | 58 - .../infinityforreddit/LoginActivity.java | 223 --- .../infinityforreddit/MainActivity.java | 1221 -------------- .../docilealligator/infinityforreddit/Message.java | 2 +- .../MessageRecyclerViewAdapter.java | 244 --- .../infinityforreddit/MessageViewModel.java | 12 +- .../ModifyCommentBottomSheetFragment.java | 84 - .../infinityforreddit/NetworkState.java | 2 +- .../ParseAndInsertNewAccountAsyncTask.java | 51 - .../infinityforreddit/ParseAndSaveAccountInfo.java | 8 +- .../infinityforreddit/ParseComment.java | 8 +- .../infinityforreddit/ParsePost.java | 8 +- .../ml/docilealligator/infinityforreddit/Post.java | 102 +- .../infinityforreddit/PostDataSource.java | 46 +- .../infinityforreddit/PostFragment.java | 667 -------- .../infinityforreddit/PostImageActivity.java | 586 ------- .../infinityforreddit/PostLinkActivity.java | 495 ------ .../infinityforreddit/PostRecyclerViewAdapter.java | 859 ---------- .../infinityforreddit/PostTextActivity.java | 495 ------ .../PostTypeBottomSheetFragment.java | 81 - .../PostUpdateEventToDetailActivity.java | 9 - .../PostUpdateEventToPostList.java | 11 - .../infinityforreddit/PostVideoActivity.java | 620 ------- .../infinityforreddit/PostViewModel.java | 20 +- .../infinityforreddit/PullNotificationWorker.java | 2 + .../infinityforreddit/ReadMessage.java | 8 +- .../infinityforreddit/RedditUtils.java | 136 +- .../ml/docilealligator/infinityforreddit/Rule.java | 8 +- .../infinityforreddit/RulesActivity.java | 279 --- .../RulesRecyclerViewAdapter.java | 92 - .../infinityforreddit/SaveThing.java | 12 +- .../infinityforreddit/SearchActivity.java | 298 ---- .../SearchPostSortTypeBottomSheetFragment.java | 82 - .../infinityforreddit/SearchResultActivity.java | 394 ----- .../SearchSubredditsResultActivity.java | 218 --- ...serAndSubredditSortTypeBottomSheetFragment.java | 68 - .../infinityforreddit/SendComment.java | 10 +- .../Settings/AboutPreferenceFragment.java | 2 +- .../AcknowledgementRecyclerViewAdapter.java | 2 +- .../Settings/CreditsPreferenceFragment.java | 2 +- .../Settings/FontSizePreferenceFragment.java | 2 +- .../Settings/MainPreferenceFragment.java | 6 +- .../infinityforreddit/SettingsActivity.java | 148 -- .../ShareDataResolverActivity.java | 77 - .../SortTypeBottomSheetFragment.java | 101 -- .../infinityforreddit/SubmitImagePostEvent.java | 11 - .../infinityforreddit/SubmitPostService.java | 27 +- .../SubmitTextOrLinkPostEvent.java | 13 - .../infinityforreddit/SubmitVideoPostEvent.java | 13 - .../SubredditListingFragment.java | 180 -- .../SubredditListingRecyclerViewAdapter.java | 226 --- .../SubredditListingViewModel.java | 14 +- .../SubredditSelectionActivity.java | 310 ---- .../infinityforreddit/SubredditSubscription.java | 20 +- .../SubscribedSubredditsListingFragment.java | 116 -- .../SubscribedSubredditsRecyclerViewAdapter.java | 152 -- .../SubscribedThingListingActivity.java | 303 ---- .../infinityforreddit/SwitchAccountAsyncTask.java | 36 - .../infinityforreddit/SwitchAccountEvent.java | 9 - .../SwitchToAnonymousAccountAsyncTask.java | 37 - .../infinityforreddit/UserFollowing.java | 20 +- .../infinityforreddit/UserListingFragment.java | 159 -- .../UserListingRecyclerViewAdapter.java | 229 --- .../infinityforreddit/UserListingViewModel.java | 14 +- .../UserThingSortTypeBottomSheetFragment.java | 88 - .../docilealligator/infinityforreddit/Utils.java | 4 +- .../infinityforreddit/ViewImageActivity.java | 462 ----- .../infinityforreddit/ViewMessageActivity.java | 318 ---- .../infinityforreddit/ViewPostDetailActivity.java | 1290 -------------- .../ViewSubredditDetailActivity.java | 655 -------- .../infinityforreddit/ViewUserDetailActivity.java | 778 --------- .../infinityforreddit/ViewVideoActivity.java | 368 ---- .../infinityforreddit/VoteThing.java | 16 +- app/src/main/res/layout/activity_account_posts.xml | 2 +- .../res/layout/activity_account_saved_thing.xml | 2 +- app/src/main/res/layout/activity_edit_comment.xml | 2 +- app/src/main/res/layout/activity_edit_post.xml | 2 +- app/src/main/res/layout/activity_login.xml | 2 +- app/src/main/res/layout/activity_view_image.xml | 2 +- app/src/main/res/layout/activity_view_message.xml | 2 +- app/src/main/res/layout/activity_view_video.xml | 2 +- app/src/main/res/layout/app_bar_main.xml | 2 +- .../main/res/layout/fragment_comments_listing.xml | 2 +- .../fragment_modify_comment_bottom_sheet.xml | 2 +- app/src/main/res/layout/fragment_post.xml | 2 +- .../main/res/menu/account_saved_thing_activity.xml | 2 +- app/src/main/res/menu/main_activity.xml | 2 +- app/src/main/res/menu/menu_search.xml | 2 +- app/src/main/res/menu/search_activity.xml | 2 +- .../res/menu/view_subreddit_detail_activity.xml | 2 +- .../main/res/menu/view_user_detail_activity.xml | 2 +- app/src/main/res/xml/about_preferences.xml | 4 +- app/src/main/res/xml/main_preferences.xml | 6 +- 206 files changed, 19468 insertions(+), 18920 deletions(-) delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/AccountPostsActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/AccountRecyclerViewAdapter.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/AccountSavedThingActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/AccountPostsActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/AccountSavedThingActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/CommentActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/EditCommentActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/EditPostActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/FilteredThingActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/LinkResolverActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/LoginActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostImageActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostLinkActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostTextActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostVideoActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/RulesActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SearchActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SearchResultActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SearchSubredditsResultActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SettingsActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ShareDataResolverActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SubredditSelectionActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SubscribedThingListingActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewImageActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewMessageActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewVideoActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/AccountRecyclerViewAdapter.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentsListingRecyclerViewAdapter.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/FlairBottomSheetRecyclerViewAdapter.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/FollowedUsersRecyclerViewAdapter.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/MessageRecyclerViewAdapter.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/RulesRecyclerViewAdapter.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/SubredditListingRecyclerViewAdapter.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/SubscribedSubredditsRecyclerViewAdapter.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/UserListingRecyclerViewAdapter.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/CheckIsFollowingUserAsyncTask.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/CheckIsSubscribedToSubredditAsyncTask.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/GetCurrentAccountAsyncTask.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/InsertSubscribedThingsAsyncTask.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/InsertUserDataAsyncTask.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/LoadSubredditIconAsyncTask.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/LoadUserDataAsyncTask.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/ParseAndInsertNewAccountAsyncTask.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/SwitchAccountAsyncTask.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/SwitchToAnonymousAccountAsyncTask.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ChangeFontSizeEvent.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ChangeNSFWBlurEvent.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ChangeNSFWEvent.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ChangeSpoilerBlurEvent.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/CheckIsFollowingUserAsyncTask.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/CheckIsSubscribedToSubredditAsyncTask.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/CommentActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/CommentAndPostRecyclerViewAdapter.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/CommentsListingFragment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/CommentsListingRecyclerViewAdapter.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/EditCommentActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/EditPostActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeFontSizeEvent.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeNSFWBlurEvent.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeNSFWEvent.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeSpoilerBlurEvent.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Event/PostUpdateEventToDetailActivity.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Event/PostUpdateEventToPostList.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Event/SubmitImagePostEvent.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Event/SubmitTextOrLinkPostEvent.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Event/SubmitVideoPostEvent.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Event/SwitchAccountEvent.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/FilteredThingActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/FlairBottomSheetFragment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/FlairBottomSheetRecyclerViewAdapter.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/FollowedUsersListingFragment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/FollowedUsersRecyclerViewAdapter.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/CommentsListingFragment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/FlairBottomSheetFragment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/FollowedUsersListingFragment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/ModifyCommentBottomSheetFragment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostTypeBottomSheetFragment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SearchPostSortTypeBottomSheetFragment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SearchUserAndSubredditSortTypeBottomSheetFragment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SortTypeBottomSheetFragment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SubredditListingFragment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SubscribedSubredditsListingFragment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/UserListingFragment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/UserThingSortTypeBottomSheetFragment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/GetCurrentAccountAsyncTask.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/InsertSubscribedThingsAsyncTask.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/InsertUserDataAsyncTask.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/LinkResolverActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/LoadSubredditIconAsyncTask.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/LoadUserDataAsyncTask.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/LoginActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/MessageRecyclerViewAdapter.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ModifyCommentBottomSheetFragment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ParseAndInsertNewAccountAsyncTask.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/PostFragment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/PostImageActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/PostLinkActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/PostTextActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/PostTypeBottomSheetFragment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/PostUpdateEventToDetailActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/PostUpdateEventToPostList.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/PostVideoActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/RulesActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/RulesRecyclerViewAdapter.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SearchPostSortTypeBottomSheetFragment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SearchResultActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SearchSubredditsResultActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SearchUserAndSubredditSortTypeBottomSheetFragment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SettingsActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ShareDataResolverActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SortTypeBottomSheetFragment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SubmitImagePostEvent.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SubmitTextOrLinkPostEvent.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SubmitVideoPostEvent.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingFragment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingRecyclerViewAdapter.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SubredditSelectionActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedSubredditsListingFragment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedSubredditsRecyclerViewAdapter.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedThingListingActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SwitchAccountAsyncTask.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SwitchAccountEvent.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SwitchToAnonymousAccountAsyncTask.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/UserListingFragment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/UserListingRecyclerViewAdapter.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/UserThingSortTypeBottomSheetFragment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ViewImageActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ViewMessageActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ViewVideoActivity.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9d4280ec..cfddbb91 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -21,11 +21,11 @@ android:theme="@style/AppTheme" android:usesCleartextTraffic="true"> - + @@ -49,41 +49,41 @@ - + @@ -153,62 +153,62 @@ @@ -218,29 +218,29 @@ = Build.VERSION_CODES.O_MR1 - && (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT - || resources.getBoolean(R.bool.isTablet))) { - Window window = getWindow(); - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - - boolean lightNavBar = false; - if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - lightNavBar = true; - } - boolean finalLightNavBar = lightNavBar; - - View decorView = window.getDecorView(); - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { - @Override - void onStateChanged(AppBarLayout appBarLayout, State state) { - if (state == State.COLLAPSED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } else if (state == State.EXPANDED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } - } - }); - - int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); - if (statusBarResourceId > 0) { - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); - params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); - toolbar.setLayoutParams(params); - } - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - mUserWhere = getIntent().getExtras().getString(EXTRA_USER_WHERE); - if(mUserWhere.equals(PostDataSource.USER_WHERE_UPVOTED)) { - toolbar.setTitle(R.string.upvoted); - } else if(mUserWhere.equals(PostDataSource.USER_WHERE_DOWNVOTED)) { - toolbar.setTitle(R.string.downvoted); - } else if(mUserWhere.equals(PostDataSource.USER_WHERE_HIDDEN)) { - toolbar.setTitle(R.string.hidden); - } else if(mUserWhere.equals(PostDataSource.USER_WHERE_GILDED)){ - toolbar.setTitle(R.string.gilded); - } - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); - - if(savedInstanceState != null) { - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); - isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); - if(!mNullAccessToken && mAccessToken == null) { - getCurrentAccountAndInitializeFragment(); - } else { - mFragment = getSupportFragmentManager().getFragment(savedInstanceState, FRAGMENT_OUT_STATE); - getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_account_posts_activity, mFragment).commit(); - } - } else { - getCurrentAccountAndInitializeFragment(); - } - } - - private void getCurrentAccountAndInitializeFragment() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - } - initializeFragment(); - }).execute(); - } - - private void initializeFragment() { - mFragment = new PostFragment(); - Bundle bundle = new Bundle(); - bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_USER); - bundle.putString(PostFragment.EXTRA_USER_NAME, mAccountName); - bundle.putString(PostFragment.EXTRA_USER_WHERE, mUserWhere); - bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_NEW); - bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); - bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - mFragment.setArguments(bundle); - getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_account_posts_activity, mFragment).commit(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.account_posts_activity, menu); - mMenu = menu; - MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_account_posts_activity); - if(isInLazyMode) { - lazyModeItem.setTitle(R.string.action_stop_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); - collapsingToolbarLayout.setLayoutParams(params); - } else { - lazyModeItem.setTitle(R.string.action_start_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); - collapsingToolbarLayout.setLayoutParams(params); - } - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case R.id.action_refresh_account_posts_activity: - if(mMenu != null) { - mMenu.findItem(R.id.action_lazy_mode_account_posts_activity).setTitle(R.string.action_start_lazy_mode); - } - if(mFragment != null) { - ((PostFragment) mFragment).refresh(); - } - return true; - case R.id.action_lazy_mode_account_posts_activity: - MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_account_posts_activity); - if(isInLazyMode) { - ((FragmentCommunicator) mFragment).stopLazyMode(); - isInLazyMode = false; - lazyModeItem.setTitle(R.string.action_start_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); - collapsingToolbarLayout.setLayoutParams(params); - } else { - if(((FragmentCommunicator) mFragment).startLazyMode()) { - isInLazyMode = true; - lazyModeItem.setTitle(R.string.action_stop_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); - collapsingToolbarLayout.setLayoutParams(params); - } - } - return true; - case android.R.id.home: - finish(); - return true; - } - return false; - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - if (mFragment != null) { - getSupportFragmentManager().putFragment(outState, FRAGMENT_OUT_STATE, mFragment); - } - outState.putBoolean(IS_IN_LAZY_MODE_STATE, isInLazyMode); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - outState.putString(ACCOUNT_NAME_STATE, mAccountName); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - @Override - public void userThingSortTypeSelected(String sortType) { - if(mFragment != null) { - ((PostFragment) mFragment).changeSortType(sortType); - } - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } - - @Subscribe - public void onChangeNSFWEvent(ChangeNSFWEvent changeNSFWEvent) { - ((FragmentCommunicator) mFragment).changeNSFW(changeNSFWEvent.nsfw); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AccountRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AccountRecyclerViewAdapter.java deleted file mode 100644 index b731be27..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/AccountRecyclerViewAdapter.java +++ /dev/null @@ -1,129 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -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.core.content.ContextCompat; -import androidx.recyclerview.widget.RecyclerView; - -import com.bumptech.glide.RequestManager; -import com.bumptech.glide.request.RequestOptions; - -import java.util.List; - -import ml.docilealligator.infinityforreddit.Account.Account; -import butterknife.BindView; -import butterknife.ButterKnife; -import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import pl.droidsonroids.gif.GifImageView; - -class AccountRecyclerViewAdapter extends RecyclerView.Adapter { - - interface ItemSelectedListener { - void accountSelected(Account account); - void addAccountSelected(); - void anonymousSelected(); - void logoutSelected(); - } - - private List mAccounts; - private String mCurrentAccountName; - private Context mContext; - private RequestManager mGlide; - private ItemSelectedListener mItemSelectedListener; - - AccountRecyclerViewAdapter(Context context, RequestManager glide, String currentAccountName, ItemSelectedListener itemSelectedListener) { - mContext = context; - mGlide = glide; - mCurrentAccountName = currentAccountName; - mItemSelectedListener = itemSelectedListener; - } - - @NonNull - @Override - public AccountViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new AccountViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_account, parent, false)); - } - - @Override - public void onBindViewHolder(@NonNull AccountViewHolder holder, int position) { - if(mAccounts == null) { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0))) - .into(holder.profileImageGifImageView); - holder.usernameTextView.setText(R.string.add_account); - holder.itemView.setOnClickListener(view -> mItemSelectedListener.addAccountSelected()); - } else { - if(position < mAccounts.size()) { - mGlide.load(mAccounts.get(position).getProfileImageUrl()) - .error(mGlide.load(R.drawable.subreddit_default_icon)) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0))) - .into(holder.profileImageGifImageView); - holder.usernameTextView.setText(mAccounts.get(position).getUsername()); - holder.itemView.setOnClickListener(view -> { - mCurrentAccountName = mAccounts.get(position).getUsername(); - mItemSelectedListener.accountSelected(mAccounts.get(position)); - }); - } else if(position == mAccounts.size()) { - holder.profileImageGifImageView.setColorFilter(ContextCompat.getColor(mContext, R.color.primaryTextColor), android.graphics.PorterDuff.Mode.SRC_IN); - mGlide.load(R.drawable.ic_outline_add_circle_outline_24px) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0))) - .into(holder.profileImageGifImageView); - holder.usernameTextView.setText(R.string.add_account); - holder.itemView.setOnClickListener(view -> mItemSelectedListener.addAccountSelected()); - } else if(position == mAccounts.size() + 1) { - holder.profileImageGifImageView.setColorFilter(ContextCompat.getColor(mContext, R.color.primaryTextColor), android.graphics.PorterDuff.Mode.SRC_IN); - mGlide.load(R.drawable.ic_outline_public_24px) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0))) - .into(holder.profileImageGifImageView); - holder.usernameTextView.setText(R.string.anonymous_account); - holder.itemView.setOnClickListener(view -> mItemSelectedListener.anonymousSelected()); - } else { - holder.profileImageGifImageView.setColorFilter(ContextCompat.getColor(mContext, R.color.primaryTextColor), android.graphics.PorterDuff.Mode.SRC_IN); - mGlide.load(R.drawable.ic_outline_block_24px) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0))) - .into(holder.profileImageGifImageView); - holder.usernameTextView.setText(R.string.log_out); - holder.itemView.setOnClickListener(view -> mItemSelectedListener.logoutSelected()); - } - } - } - - @Override - public int getItemCount() { - if(mAccounts == null) { - return 1; - } else { - if(mCurrentAccountName == null) { - return mAccounts.size() + 1; - } else { - return mAccounts.size() + 3; - } - } - } - - @Override - public void onViewRecycled(@NonNull AccountViewHolder holder) { - mGlide.clear(holder.profileImageGifImageView); - holder.profileImageGifImageView.clearColorFilter(); - } - - void changeAccountsDataset(List accounts) { - mAccounts = accounts; - notifyDataSetChanged(); - } - - class AccountViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.profile_image_item_account) GifImageView profileImageGifImageView; - @BindView(R.id.username_text_view_item_account) TextView usernameTextView; - - AccountViewHolder(@NonNull View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AccountSavedThingActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AccountSavedThingActivity.java deleted file mode 100644 index 367c7439..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/AccountSavedThingActivity.java +++ /dev/null @@ -1,402 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentPagerAdapter; -import androidx.viewpager.widget.ViewPager; - -import com.google.android.material.appbar.AppBarLayout; -import com.google.android.material.appbar.CollapsingToolbarLayout; -import com.google.android.material.tabs.TabLayout; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class AccountSavedThingActivity extends AppCompatActivity { - - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - private static final String ACCOUNT_NAME_STATE = "ANS"; - private static final String IS_IN_LAZY_MODE_STATE = "IILMS"; - - @BindView(R.id.collapsing_toolbar_layout_account_saved_thing_activity) CollapsingToolbarLayout collapsingToolbarLayout; - @BindView(R.id.appbar_layout_account_saved_thing_activity) AppBarLayout appBarLayout; - @BindView(R.id.toolbar_account_saved_thing_activity) Toolbar toolbar; - @BindView(R.id.tab_layout_tab_layout_account_saved_thing_activity_activity) TabLayout tabLayout; - @BindView(R.id.view_pager_account_saved_thing_activity) ViewPager viewPager; - - private SectionsPagerAdapter sectionsPagerAdapter; - private Menu mMenu; - private AppBarLayout.LayoutParams params; - - private boolean mNullAccessToken = false; - private String mAccessToken; - private String mAccountName; - private boolean isInLazyMode = false; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_account_saved_thing); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - Resources resources = getResources(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 - && (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT - || resources.getBoolean(R.bool.isTablet))) { - Window window = getWindow(); - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - - boolean lightNavBar = false; - if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - lightNavBar = true; - } - boolean finalLightNavBar = lightNavBar; - - View decorView = window.getDecorView(); - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { - @Override - void onStateChanged(AppBarLayout appBarLayout, State state) { - if (state == State.COLLAPSED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } else if (state == State.EXPANDED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } - } - }); - - int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); - if (statusBarResourceId > 0) { - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); - params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); - toolbar.setLayoutParams(params); - } - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); - - if(savedInstanceState != null) { - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); - isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); - if(!mNullAccessToken && mAccessToken == null) { - getCurrentAccountAndInitializeViewPager(); - } else { - initializeViewPager(); - } - } else { - getCurrentAccountAndInitializeViewPager(); - } - } - - private void getCurrentAccountAndInitializeViewPager() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - } - initializeViewPager(); - }).execute(); - } - - private void initializeViewPager() { - sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); - viewPager.setAdapter(sectionsPagerAdapter); - viewPager.setOffscreenPageLimit(2); - tabLayout.setupWithViewPager(viewPager); - - viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - - } - - @Override - public void onPageSelected(int position) { - if(isInLazyMode) { - if(viewPager.getCurrentItem() == 0) { - sectionsPagerAdapter.resumeLazyMode(); - } else { - sectionsPagerAdapter.pauseLazyMode(); - } - } - } - - @Override - public void onPageScrollStateChanged(int state) { - - } - }); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.account_saved_thing_activity, menu); - mMenu = menu; - MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_account_saved_thing_activity); - if (isInLazyMode) { - lazyModeItem.setTitle(R.string.action_stop_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); - collapsingToolbarLayout.setLayoutParams(params); - } else { - lazyModeItem.setTitle(R.string.action_start_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); - collapsingToolbarLayout.setLayoutParams(params); - } - - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; - case R.id.action_refresh_account_saved_thing_activity: - if(mMenu != null) { - mMenu.findItem(R.id.action_lazy_mode_account_saved_thing_activity).setTitle(R.string.action_start_lazy_mode); - } - sectionsPagerAdapter.refresh(); - return true; - case R.id.action_lazy_mode_account_saved_thing_activity: - MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_account_saved_thing_activity); - if(isInLazyMode) { - isInLazyMode = false; - sectionsPagerAdapter.stopLazyMode(); - lazyModeItem.setTitle(R.string.action_start_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); - collapsingToolbarLayout.setLayoutParams(params); - } else { - isInLazyMode = true; - if(sectionsPagerAdapter.startLazyMode()) { - lazyModeItem.setTitle(R.string.action_stop_lazy_mode); - appBarLayout.setExpanded(false); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); - collapsingToolbarLayout.setLayoutParams(params); - } else { - isInLazyMode = false; - } - } - return true; - } - return false; - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean(IS_IN_LAZY_MODE_STATE, isInLazyMode); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - outState.putString(ACCOUNT_NAME_STATE, mAccountName); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } - - @Subscribe - public void onChangeNSFWEvent(ChangeNSFWEvent changeNSFWEvent) { - sectionsPagerAdapter.changeNSFW(changeNSFWEvent.nsfw); - } - - private class SectionsPagerAdapter extends FragmentPagerAdapter { - private PostFragment postFragment; - private CommentsListingFragment commentsListingFragment; - - SectionsPagerAdapter(FragmentManager fm) { - super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); - } - - @NonNull - @Override - public Fragment getItem(int position) { - if (position == 0) { - PostFragment fragment = new PostFragment(); - Bundle bundle = new Bundle(); - bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_USER); - bundle.putString(PostFragment.EXTRA_USER_NAME, mAccountName); - bundle.putString(PostFragment.EXTRA_USER_WHERE, PostDataSource.USER_WHERE_SAVED); - bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_NEW); - bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); - bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - fragment.setArguments(bundle); - return fragment; - } - CommentsListingFragment fragment = new CommentsListingFragment(); - Bundle bundle = new Bundle(); - bundle.putString(CommentsListingFragment.EXTRA_USERNAME, mAccountName); - bundle.putString(CommentsListingFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - bundle.putString(CommentsListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); - bundle.putBoolean(CommentsListingFragment.EXTRA_ARE_SAVED_COMMENTS, true); - fragment.setArguments(bundle); - return fragment; - } - - @Override - public int getCount() { - return 2; - } - - @Override - public CharSequence getPageTitle(int position) { - switch (position) { - case 0: - return "Posts"; - case 1: - return "Comments"; - } - return null; - } - - @NonNull - @Override - public Object instantiateItem(@NonNull ViewGroup container, int position) { - Fragment fragment = (Fragment) super.instantiateItem(container, position); - switch (position) { - case 0: - postFragment = (PostFragment) fragment; - break; - case 1: - commentsListingFragment = (CommentsListingFragment) fragment; - } - return fragment; - } - - public void refresh() { - if (viewPager.getCurrentItem() == 0) { - if(postFragment != null) { - postFragment.refresh(); - } - } else { - if(commentsListingFragment != null) { - commentsListingFragment.refresh(); - } - } - } - - boolean startLazyMode() { - if(postFragment != null) { - return ((FragmentCommunicator) postFragment).startLazyMode(); - } - return false; - } - - void stopLazyMode() { - if(postFragment != null) { - ((FragmentCommunicator) postFragment).stopLazyMode(); - } - } - - void resumeLazyMode() { - if(postFragment != null) { - ((FragmentCommunicator) postFragment).resumeLazyMode(false); - } - } - - void pauseLazyMode() { - if(postFragment != null) { - ((FragmentCommunicator) postFragment).pauseLazyMode(false); - } - } - - public void changeNSFW(boolean nsfw) { - if(postFragment != null) { - postFragment.changeNSFW(nsfw); - } - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/AccountPostsActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/AccountPostsActivity.java new file mode 100644 index 00000000..8498a4ea --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/AccountPostsActivity.java @@ -0,0 +1,305 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.Fragment; + +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.appbar.CollapsingToolbarLayout; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import javax.inject.Inject; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; +import ml.docilealligator.infinityforreddit.Event.ChangeNSFWEvent; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.FragmentCommunicator; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.Fragment.PostFragment; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import ml.docilealligator.infinityforreddit.Fragment.UserThingSortTypeBottomSheetFragment; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class AccountPostsActivity extends AppCompatActivity implements UserThingSortTypeBottomSheetFragment.UserThingSortTypeSelectionCallback { + + static final String EXTRA_USER_WHERE = "EUW"; + + private static final String IS_IN_LAZY_MODE_STATE = "IILMS"; + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + private static final String ACCOUNT_NAME_STATE = "ANS"; + private static final String FRAGMENT_OUT_STATE = "FOS"; + + @BindView(R.id.collapsing_toolbar_layout_account_posts_activity) CollapsingToolbarLayout collapsingToolbarLayout; + @BindView(R.id.appbar_layout_account_posts_activity) AppBarLayout appBarLayout; + @BindView(R.id.toolbar_account_posts_activity) Toolbar toolbar; + + private boolean isInLazyMode = false; + private boolean mNullAccessToken = false; + private String mAccessToken; + private String mAccountName; + private String mUserWhere; + + private Fragment mFragment; + private Menu mMenu; + private AppBarLayout.LayoutParams params; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_account_posts); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + Resources resources = getResources(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 + && (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT + || resources.getBoolean(R.bool.isTablet))) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + + boolean lightNavBar = false; + if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + lightNavBar = true; + } + boolean finalLightNavBar = lightNavBar; + + View decorView = window.getDecorView(); + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, State state) { + if (state == State.COLLAPSED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } else if (state == State.EXPANDED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } + } + }); + + int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (statusBarResourceId > 0) { + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); + params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); + toolbar.setLayoutParams(params); + } + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + mUserWhere = getIntent().getExtras().getString(EXTRA_USER_WHERE); + if(mUserWhere.equals(PostDataSource.USER_WHERE_UPVOTED)) { + toolbar.setTitle(R.string.upvoted); + } else if(mUserWhere.equals(PostDataSource.USER_WHERE_DOWNVOTED)) { + toolbar.setTitle(R.string.downvoted); + } else if(mUserWhere.equals(PostDataSource.USER_WHERE_HIDDEN)) { + toolbar.setTitle(R.string.hidden); + } else if(mUserWhere.equals(PostDataSource.USER_WHERE_GILDED)){ + toolbar.setTitle(R.string.gilded); + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); + + if(savedInstanceState != null) { + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); + isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccountAndInitializeFragment(); + } else { + mFragment = getSupportFragmentManager().getFragment(savedInstanceState, FRAGMENT_OUT_STATE); + getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_account_posts_activity, mFragment).commit(); + } + } else { + getCurrentAccountAndInitializeFragment(); + } + } + + private void getCurrentAccountAndInitializeFragment() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + initializeFragment(); + }).execute(); + } + + private void initializeFragment() { + mFragment = new PostFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_USER); + bundle.putString(PostFragment.EXTRA_USER_NAME, mAccountName); + bundle.putString(PostFragment.EXTRA_USER_WHERE, mUserWhere); + bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_NEW); + bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); + bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + mFragment.setArguments(bundle); + getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_account_posts_activity, mFragment).commit(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.account_posts_activity, menu); + mMenu = menu; + MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_account_posts_activity); + if(isInLazyMode) { + lazyModeItem.setTitle(R.string.action_stop_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); + collapsingToolbarLayout.setLayoutParams(params); + } else { + lazyModeItem.setTitle(R.string.action_start_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); + collapsingToolbarLayout.setLayoutParams(params); + } + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case R.id.action_refresh_account_posts_activity: + if(mMenu != null) { + mMenu.findItem(R.id.action_lazy_mode_account_posts_activity).setTitle(R.string.action_start_lazy_mode); + } + if(mFragment != null) { + ((PostFragment) mFragment).refresh(); + } + return true; + case R.id.action_lazy_mode_account_posts_activity: + MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_account_posts_activity); + if(isInLazyMode) { + ((FragmentCommunicator) mFragment).stopLazyMode(); + isInLazyMode = false; + lazyModeItem.setTitle(R.string.action_start_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); + collapsingToolbarLayout.setLayoutParams(params); + } else { + if(((FragmentCommunicator) mFragment).startLazyMode()) { + isInLazyMode = true; + lazyModeItem.setTitle(R.string.action_stop_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); + collapsingToolbarLayout.setLayoutParams(params); + } + } + return true; + case android.R.id.home: + finish(); + return true; + } + return false; + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + if (mFragment != null) { + getSupportFragmentManager().putFragment(outState, FRAGMENT_OUT_STATE, mFragment); + } + outState.putBoolean(IS_IN_LAZY_MODE_STATE, isInLazyMode); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putString(ACCOUNT_NAME_STATE, mAccountName); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void userThingSortTypeSelected(String sortType) { + if(mFragment != null) { + ((PostFragment) mFragment).changeSortType(sortType); + } + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } + + @Subscribe + public void onChangeNSFWEvent(ChangeNSFWEvent changeNSFWEvent) { + ((FragmentCommunicator) mFragment).changeNSFW(changeNSFWEvent.nsfw); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/AccountSavedThingActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/AccountSavedThingActivity.java new file mode 100644 index 00000000..9d60f595 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/AccountSavedThingActivity.java @@ -0,0 +1,417 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.appbar.CollapsingToolbarLayout; +import com.google.android.material.tabs.TabLayout; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; +import ml.docilealligator.infinityforreddit.Event.ChangeNSFWEvent; +import ml.docilealligator.infinityforreddit.Fragment.CommentsListingFragment; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.FragmentCommunicator; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.Fragment.PostFragment; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class AccountSavedThingActivity extends AppCompatActivity { + + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + private static final String ACCOUNT_NAME_STATE = "ANS"; + private static final String IS_IN_LAZY_MODE_STATE = "IILMS"; + + @BindView(R.id.collapsing_toolbar_layout_account_saved_thing_activity) CollapsingToolbarLayout collapsingToolbarLayout; + @BindView(R.id.appbar_layout_account_saved_thing_activity) AppBarLayout appBarLayout; + @BindView(R.id.toolbar_account_saved_thing_activity) Toolbar toolbar; + @BindView(R.id.tab_layout_tab_layout_account_saved_thing_activity_activity) TabLayout tabLayout; + @BindView(R.id.view_pager_account_saved_thing_activity) ViewPager viewPager; + + private SectionsPagerAdapter sectionsPagerAdapter; + private Menu mMenu; + private AppBarLayout.LayoutParams params; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String mAccountName; + private boolean isInLazyMode = false; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_account_saved_thing); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + Resources resources = getResources(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 + && (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT + || resources.getBoolean(R.bool.isTablet))) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + + boolean lightNavBar = false; + if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + lightNavBar = true; + } + boolean finalLightNavBar = lightNavBar; + + View decorView = window.getDecorView(); + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, State state) { + if (state == State.COLLAPSED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } else if (state == State.EXPANDED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } + } + }); + + int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (statusBarResourceId > 0) { + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); + params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); + toolbar.setLayoutParams(params); + } + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); + + if(savedInstanceState != null) { + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); + isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccountAndInitializeViewPager(); + } else { + initializeViewPager(); + } + } else { + getCurrentAccountAndInitializeViewPager(); + } + } + + private void getCurrentAccountAndInitializeViewPager() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + initializeViewPager(); + }).execute(); + } + + private void initializeViewPager() { + sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); + viewPager.setAdapter(sectionsPagerAdapter); + viewPager.setOffscreenPageLimit(2); + tabLayout.setupWithViewPager(viewPager); + + viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + if(isInLazyMode) { + if(viewPager.getCurrentItem() == 0) { + sectionsPagerAdapter.resumeLazyMode(); + } else { + sectionsPagerAdapter.pauseLazyMode(); + } + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.account_saved_thing_activity, menu); + mMenu = menu; + MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_account_saved_thing_activity); + if (isInLazyMode) { + lazyModeItem.setTitle(R.string.action_stop_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); + collapsingToolbarLayout.setLayoutParams(params); + } else { + lazyModeItem.setTitle(R.string.action_start_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); + collapsingToolbarLayout.setLayoutParams(params); + } + + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + case R.id.action_refresh_account_saved_thing_activity: + if(mMenu != null) { + mMenu.findItem(R.id.action_lazy_mode_account_saved_thing_activity).setTitle(R.string.action_start_lazy_mode); + } + sectionsPagerAdapter.refresh(); + return true; + case R.id.action_lazy_mode_account_saved_thing_activity: + MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_account_saved_thing_activity); + if(isInLazyMode) { + isInLazyMode = false; + sectionsPagerAdapter.stopLazyMode(); + lazyModeItem.setTitle(R.string.action_start_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); + collapsingToolbarLayout.setLayoutParams(params); + } else { + isInLazyMode = true; + if(sectionsPagerAdapter.startLazyMode()) { + lazyModeItem.setTitle(R.string.action_stop_lazy_mode); + appBarLayout.setExpanded(false); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); + collapsingToolbarLayout.setLayoutParams(params); + } else { + isInLazyMode = false; + } + } + return true; + } + return false; + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(IS_IN_LAZY_MODE_STATE, isInLazyMode); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putString(ACCOUNT_NAME_STATE, mAccountName); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } + + @Subscribe + public void onChangeNSFWEvent(ChangeNSFWEvent changeNSFWEvent) { + sectionsPagerAdapter.changeNSFW(changeNSFWEvent.nsfw); + } + + private class SectionsPagerAdapter extends FragmentPagerAdapter { + private PostFragment postFragment; + private CommentsListingFragment commentsListingFragment; + + SectionsPagerAdapter(FragmentManager fm) { + super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); + } + + @NonNull + @Override + public Fragment getItem(int position) { + if (position == 0) { + PostFragment fragment = new PostFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_USER); + bundle.putString(PostFragment.EXTRA_USER_NAME, mAccountName); + bundle.putString(PostFragment.EXTRA_USER_WHERE, PostDataSource.USER_WHERE_SAVED); + bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_NEW); + bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); + bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + fragment.setArguments(bundle); + return fragment; + } + CommentsListingFragment fragment = new CommentsListingFragment(); + Bundle bundle = new Bundle(); + bundle.putString(CommentsListingFragment.EXTRA_USERNAME, mAccountName); + bundle.putString(CommentsListingFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + bundle.putString(CommentsListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); + bundle.putBoolean(CommentsListingFragment.EXTRA_ARE_SAVED_COMMENTS, true); + fragment.setArguments(bundle); + return fragment; + } + + @Override + public int getCount() { + return 2; + } + + @Override + public CharSequence getPageTitle(int position) { + switch (position) { + case 0: + return "Posts"; + case 1: + return "Comments"; + } + return null; + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + Fragment fragment = (Fragment) super.instantiateItem(container, position); + switch (position) { + case 0: + postFragment = (PostFragment) fragment; + break; + case 1: + commentsListingFragment = (CommentsListingFragment) fragment; + } + return fragment; + } + + public void refresh() { + if (viewPager.getCurrentItem() == 0) { + if(postFragment != null) { + postFragment.refresh(); + } + } else { + if(commentsListingFragment != null) { + commentsListingFragment.refresh(); + } + } + } + + boolean startLazyMode() { + if(postFragment != null) { + return ((FragmentCommunicator) postFragment).startLazyMode(); + } + return false; + } + + void stopLazyMode() { + if(postFragment != null) { + ((FragmentCommunicator) postFragment).stopLazyMode(); + } + } + + void resumeLazyMode() { + if(postFragment != null) { + ((FragmentCommunicator) postFragment).resumeLazyMode(false); + } + } + + void pauseLazyMode() { + if(postFragment != null) { + ((FragmentCommunicator) postFragment).pauseLazyMode(false); + } + } + + public void changeNSFW(boolean nsfw) { + if(postFragment != null) { + postFragment.changeNSFW(nsfw); + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/CommentActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/CommentActivity.java new file mode 100644 index 00000000..7acb26f9 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/CommentActivity.java @@ -0,0 +1,284 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.text.util.Linkify; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.content.ContextCompat; + +import com.google.android.material.snackbar.Snackbar; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import io.noties.markwon.AbstractMarkwonPlugin; +import io.noties.markwon.Markwon; +import io.noties.markwon.MarkwonConfiguration; +import io.noties.markwon.linkify.LinkifyPlugin; +import ml.docilealligator.infinityforreddit.CommentData; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SendComment; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class CommentActivity extends AppCompatActivity { + + public static final String EXTRA_COMMENT_PARENT_TEXT_KEY = "ECPTK"; + public static final String EXTRA_PARENT_FULLNAME_KEY = "EPFK"; + public static final String EXTRA_COMMENT_DATA_KEY = "ECDK"; + public static final String EXTRA_PARENT_DEPTH_KEY = "EPDK"; + public static final String EXTRA_PARENT_POSITION_KEY = "EPPK"; + public static final String EXTRA_IS_REPLYING_KEY = "EIRK"; + public static final int WRITE_COMMENT_REQUEST_CODE = 1; + + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + + @BindView(R.id.coordinator_layout_comment_activity) CoordinatorLayout coordinatorLayout; + @BindView(R.id.toolbar_comment_activity) Toolbar toolbar; + @BindView(R.id.comment_parent_markwon_view_comment_activity) TextView commentParentMarkwonView; + @BindView(R.id.comment_edit_text_comment_activity) EditText commentEditText; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String parentFullname; + private int parentDepth; + private int parentPosition; + private boolean isReplying; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_comment); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Window window = getWindow(); + if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + if(savedInstanceState == null) { + getCurrentAccount(); + } else { + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccount(); + } + } + + Intent intent = getIntent(); + Markwon markwon = Markwon.builder(this) + .usePlugin(new AbstractMarkwonPlugin() { + @Override + public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { + builder.linkResolver((view, link) -> { + Intent intent = new Intent(CommentActivity.this, LinkResolverActivity.class); + Uri uri = Uri.parse(link); + if(uri.getScheme() == null && uri.getHost() == null) { + intent.setData(LinkResolverActivity.getRedditUriByPath(link)); + } else { + intent.setData(uri); + } + startActivity(intent); + }); + } + }) + .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) + .build(); + markwon.setMarkdown(commentParentMarkwonView, intent.getStringExtra(EXTRA_COMMENT_PARENT_TEXT_KEY)); + parentFullname = intent.getStringExtra(EXTRA_PARENT_FULLNAME_KEY); + parentDepth = intent.getExtras().getInt(EXTRA_PARENT_DEPTH_KEY); + parentPosition = intent.getExtras().getInt(EXTRA_PARENT_POSITION_KEY); + isReplying = intent.getExtras().getBoolean(EXTRA_IS_REPLYING_KEY); + if(isReplying) { + toolbar.setTitle(getString(R.string.comment_activity_label_is_replying)); + } + + setSupportActionBar(toolbar); + + commentEditText.requestFocus(); + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + if(imm != null) { + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + } + } + + private void getCurrentAccount() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + } + }).execute(); + } + + @Override + protected void onPause() { + super.onPause(); + InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); + if(imm != null) { + imm.hideSoftInputFromWindow(commentEditText.getWindowToken(), 0); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.comment_activity, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + case R.id.action_send_comment_activity: + if(commentEditText.getText() == null || commentEditText.getText().toString().equals("")) { + Snackbar.make(coordinatorLayout, R.string.comment_content_required, Snackbar.LENGTH_SHORT).show(); + return true; + } + + item.setEnabled(false); + item.getIcon().setAlpha(130); + Snackbar sendingSnackbar = Snackbar.make(coordinatorLayout, R.string.sending_comment, Snackbar.LENGTH_INDEFINITE); + sendingSnackbar.show(); + + SendComment.sendComment(commentEditText.getText().toString(), parentFullname, parentDepth, + getResources().getConfiguration().locale, mOauthRetrofit, + mAccessToken, + new SendComment.SendCommentListener() { + @Override + public void sendCommentSuccess(CommentData commentData) { + Toast.makeText(CommentActivity.this, R.string.send_comment_success, Toast.LENGTH_SHORT).show(); + Intent returnIntent = new Intent(); + returnIntent.putExtra(EXTRA_COMMENT_DATA_KEY, commentData); + returnIntent.putExtra(EXTRA_PARENT_FULLNAME_KEY, parentFullname); + if(isReplying) { + returnIntent.putExtra(EXTRA_PARENT_POSITION_KEY, parentPosition); + } + setResult(RESULT_OK, returnIntent); + finish(); + } + + @Override + public void sendCommentFailed(@Nullable String errorMessage) { + sendingSnackbar.dismiss(); + item.setEnabled(true); + item.getIcon().setAlpha(255); + + if(errorMessage == null) { + Snackbar.make(coordinatorLayout, R.string.send_comment_failed, Snackbar.LENGTH_SHORT).show(); + } else { + Snackbar.make(coordinatorLayout, errorMessage, Snackbar.LENGTH_SHORT).show(); + } + } + }); + return true; + } + + return false; + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/EditCommentActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/EditCommentActivity.java new file mode 100644 index 00000000..91551d24 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/EditCommentActivity.java @@ -0,0 +1,217 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.content.ContextCompat; + +import com.google.android.material.snackbar.Snackbar; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import java.util.HashMap; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditAPI; +import ml.docilealligator.infinityforreddit.RedditUtils; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class EditCommentActivity extends AppCompatActivity { + + public static final String EXTRA_CONTENT = "EC"; + public static final String EXTRA_FULLNAME = "EF"; + public static final String EXTRA_ACCESS_TOKEN = "EAT"; + public static final String EXTRA_POSITION = "EP"; + + static final String EXTRA_EDITED_COMMENT_CONTENT = "EECC"; + static final String EXTRA_EDITED_COMMENT_POSITION = "EECP"; + + @BindView(R.id.coordinator_layout_edit_comment_activity) CoordinatorLayout coordinatorLayout; + @BindView(R.id.toolbar_edit_comment_activity) Toolbar toolbar; + @BindView(R.id.post_text_content_edit_text_edit_comment_activity) EditText contentEditText; + + private String mFullName; + private String mAccessToken; + private boolean isSubmitting = false; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_edit_comment); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Window window = getWindow(); + if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + mFullName = getIntent().getExtras().getString(EXTRA_FULLNAME); + mAccessToken = getIntent().getExtras().getString(EXTRA_ACCESS_TOKEN); + contentEditText.setText(getIntent().getExtras().getString(EXTRA_CONTENT)); + + contentEditText.requestFocus(); + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + if(imm != null) { + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + } + } + + @Override + protected void onPause() { + super.onPause(); + InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); + if(imm != null) { + imm.hideSoftInputFromWindow(contentEditText.getWindowToken(), 0); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.edit_comment_activity, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if(item.getItemId() == R.id.action_send_edit_comment_activity) { + if(!isSubmitting) { + isSubmitting = true; + + Snackbar.make(coordinatorLayout, R.string.posting, Snackbar.LENGTH_SHORT).show(); + + String content = contentEditText.getText().toString(); + + Map params = new HashMap<>(); + params.put(RedditUtils.THING_ID_KEY, mFullName); + params.put(RedditUtils.TEXT_KEY, content); + + mOauthRetrofit.create(RedditAPI.class) + .editPostOrComment(RedditUtils.getOAuthHeader(mAccessToken), params) + .enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + isSubmitting = false; + if(response.isSuccessful()) { + Toast.makeText(EditCommentActivity.this, R.string.edit_success, Toast.LENGTH_SHORT).show(); + + Intent returnIntent = new Intent(); + returnIntent.putExtra(EXTRA_EDITED_COMMENT_CONTENT, content); + returnIntent.putExtra(EXTRA_EDITED_COMMENT_POSITION, getIntent().getExtras().getInt(EXTRA_POSITION)); + setResult(RESULT_OK, returnIntent); + + finish(); + } else { + Snackbar.make(coordinatorLayout, R.string.post_failed, Snackbar.LENGTH_SHORT).show(); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + isSubmitting = false; + Snackbar.make(coordinatorLayout, R.string.post_failed, Snackbar.LENGTH_SHORT).show(); + } + }); + + } + return true; + } else if(item.getItemId() == android.R.id.home) { + finish(); + return true; + } + return false; + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/EditPostActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/EditPostActivity.java new file mode 100644 index 00000000..e09466d4 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/EditPostActivity.java @@ -0,0 +1,207 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.content.ContextCompat; + +import com.google.android.material.snackbar.Snackbar; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import java.util.HashMap; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditAPI; +import ml.docilealligator.infinityforreddit.RedditUtils; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class EditPostActivity extends AppCompatActivity { + + static final String EXTRA_TITLE = "ET"; + static final String EXTRA_CONTENT = "EC"; + static final String EXTRA_FULLNAME = "EF"; + static final String EXTRA_ACCESS_TOKEN = "EAT"; + + @BindView(R.id.coordinator_layout_edit_post_activity) CoordinatorLayout coordinatorLayout; + @BindView(R.id.toolbar_edit_post_activity) Toolbar toolbar; + @BindView(R.id.post_title_text_view_edit_post_activity) TextView titleTextView; + @BindView(R.id.post_text_content_edit_text_edit_post_activity) EditText contentEditText; + + private String mFullName; + private String mAccessToken; + private boolean isSubmitting = false; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_edit_post); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Window window = getWindow(); + if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + mFullName = getIntent().getExtras().getString(EXTRA_FULLNAME); + mAccessToken = getIntent().getExtras().getString(EXTRA_ACCESS_TOKEN); + titleTextView.setText(getIntent().getExtras().getString(EXTRA_TITLE)); + contentEditText.setText(getIntent().getExtras().getString(EXTRA_CONTENT)); + + contentEditText.requestFocus(); + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + if(imm != null) { + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + } + } + + @Override + protected void onPause() { + super.onPause(); + InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); + if(imm != null) { + imm.hideSoftInputFromWindow(contentEditText.getWindowToken(), 0); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.edit_post_activity, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if(item.getItemId() == R.id.action_send_edit_post_activity) { + if(!isSubmitting) { + isSubmitting = true; + + Snackbar.make(coordinatorLayout, R.string.posting, Snackbar.LENGTH_SHORT).show(); + + Map params = new HashMap<>(); + params.put(RedditUtils.THING_ID_KEY, mFullName); + params.put(RedditUtils.TEXT_KEY, contentEditText.getText().toString()); + + mOauthRetrofit.create(RedditAPI.class) + .editPostOrComment(RedditUtils.getOAuthHeader(mAccessToken), params) + .enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + isSubmitting = false; + Toast.makeText(EditPostActivity.this, R.string.edit_success, Toast.LENGTH_SHORT).show(); + Intent returnIntent = new Intent(); + setResult(RESULT_OK, returnIntent); + finish(); + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + isSubmitting = false; + Snackbar.make(coordinatorLayout, R.string.post_failed, Snackbar.LENGTH_SHORT).show(); + } + }); + + } + return true; + } else if(item.getItemId() == android.R.id.home) { + finish(); + return true; + } + return false; + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/FilteredThingActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/FilteredThingActivity.java new file mode 100644 index 00000000..9b0e1844 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/FilteredThingActivity.java @@ -0,0 +1,402 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.Fragment; + +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.appbar.CollapsingToolbarLayout; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import javax.inject.Inject; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.FragmentCommunicator; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.Post; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.Fragment.PostFragment; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.Fragment.SearchPostSortTypeBottomSheetFragment; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.Fragment.SortTypeBottomSheetFragment; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import ml.docilealligator.infinityforreddit.Fragment.UserThingSortTypeBottomSheetFragment; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class FilteredThingActivity extends AppCompatActivity implements SortTypeBottomSheetFragment.SortTypeSelectionCallback, + SearchPostSortTypeBottomSheetFragment.SearchSortTypeSelectionCallback, UserThingSortTypeBottomSheetFragment.UserThingSortTypeSelectionCallback { + + public static final String EXTRA_NAME = "ESN"; + public static final String EXTRA_QUERY = "EQ"; + public static final String EXTRA_FILTER = "EF"; + public static final String EXTRA_POST_TYPE = "EPT"; + public static final String EXTRA_SORT_TYPE = "EST"; + public static final String EXTRA_USER_WHERE = "EUW"; + + private static final String IS_IN_LAZY_MODE_STATE = "IILMS"; + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + private static final String FRAGMENT_OUT_STATE = "FOS"; + + @BindView(R.id.appbar_layout_filtered_posts_activity) AppBarLayout appBarLayout; + @BindView(R.id.collapsing_toolbar_layout_filtered_posts_activity) CollapsingToolbarLayout collapsingToolbarLayout; + @BindView(R.id.toolbar_filtered_posts_activity) Toolbar toolbar; + + private boolean isInLazyMode = false; + private boolean mNullAccessToken = false; + private String mAccessToken; + private String name; + private int postType; + + private Fragment mFragment; + private Menu mMenu; + private AppBarLayout.LayoutParams params; + + private SortTypeBottomSheetFragment bestSortTypeBottomSheetFragment; + private SortTypeBottomSheetFragment popularAndAllSortTypeBottomSheetFragment; + private SortTypeBottomSheetFragment subredditSortTypeBottomSheetFragment; + private UserThingSortTypeBottomSheetFragment userThingSortTypeBottomSheetFragment; + private SearchPostSortTypeBottomSheetFragment searchPostSortTypeBottomSheetFragment; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_filtered_thing); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + Resources resources = getResources(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 + && (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT + || resources.getBoolean(R.bool.isTablet))) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + + boolean lightNavBar = false; + if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + lightNavBar = true; + } + boolean finalLightNavBar = lightNavBar; + + View decorView = window.getDecorView(); + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, State state) { + if (state == State.COLLAPSED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } else if (state == State.EXPANDED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } + } + }); + + int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (statusBarResourceId > 0) { + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); + params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); + toolbar.setLayoutParams(params); + } + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); + + name = getIntent().getStringExtra(EXTRA_NAME); + postType = getIntent().getIntExtra(EXTRA_POST_TYPE, PostDataSource.TYPE_FRONT_PAGE); + int filter = getIntent().getIntExtra(EXTRA_FILTER, Post.TEXT_TYPE); + String sortType = getIntent().getStringExtra(EXTRA_SORT_TYPE); + + if(savedInstanceState != null) { + isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccountAndBindView(filter, sortType); + } else { + mFragment = getSupportFragmentManager().getFragment(savedInstanceState, FRAGMENT_OUT_STATE); + getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_filtered_posts_activity, mFragment).commit(); + bindView(filter, sortType, false); + } + } else { + getCurrentAccountAndBindView(filter, sortType); + } + } + + private void getCurrentAccountAndBindView(int filter, String sortType) { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + } + bindView(filter, sortType, true); + }).execute(); + } + + private void bindView(int filter, String sortType, boolean initializeFragment) { + switch (postType) { + case PostDataSource.TYPE_FRONT_PAGE: + getSupportActionBar().setTitle(name); + + bestSortTypeBottomSheetFragment = new SortTypeBottomSheetFragment(); + Bundle bestBundle = new Bundle(); + bestBundle.putBoolean(SortTypeBottomSheetFragment.EXTRA_NO_BEST_TYPE, false); + bestSortTypeBottomSheetFragment.setArguments(bestBundle); + break; + case PostDataSource.TYPE_SEARCH: + getSupportActionBar().setTitle(R.string.search); + + searchPostSortTypeBottomSheetFragment = new SearchPostSortTypeBottomSheetFragment(); + Bundle searchBundle = new Bundle(); + searchPostSortTypeBottomSheetFragment.setArguments(searchBundle); + break; + case PostDataSource.TYPE_SUBREDDIT: + if(name.equals("popular") || name.equals("all")) { + getSupportActionBar().setTitle(name.substring(0, 1).toUpperCase() + name.substring(1)); + + popularAndAllSortTypeBottomSheetFragment = new SortTypeBottomSheetFragment(); + Bundle popularBundle = new Bundle(); + popularBundle.putBoolean(SortTypeBottomSheetFragment.EXTRA_NO_BEST_TYPE, true); + popularAndAllSortTypeBottomSheetFragment.setArguments(popularBundle); + } else { + String subredditNamePrefixed = "r/" + name; + getSupportActionBar().setTitle(subredditNamePrefixed); + + subredditSortTypeBottomSheetFragment = new SortTypeBottomSheetFragment(); + Bundle bottomSheetBundle = new Bundle(); + bottomSheetBundle.putBoolean(SortTypeBottomSheetFragment.EXTRA_NO_BEST_TYPE, true); + subredditSortTypeBottomSheetFragment.setArguments(bottomSheetBundle); + } + break; + case PostDataSource.TYPE_USER: + String usernamePrefixed = "u/" + name; + getSupportActionBar().setTitle(usernamePrefixed); + + userThingSortTypeBottomSheetFragment = new UserThingSortTypeBottomSheetFragment(); + break; + } + + switch (filter) { + case Post.NSFW_TYPE: + toolbar.setSubtitle(R.string.nsfw); + break; + case Post.TEXT_TYPE: + toolbar.setSubtitle(R.string.text); + break; + case Post.LINK_TYPE: + case Post.NO_PREVIEW_LINK_TYPE: + toolbar.setSubtitle(R.string.link); + break; + case Post.IMAGE_TYPE: + toolbar.setSubtitle(R.string.image); + break; + case Post.VIDEO_TYPE: + toolbar.setSubtitle(R.string.video); + break; + case Post.GIF_VIDEO_TYPE: + toolbar.setSubtitle(R.string.gif); + } + + if(initializeFragment) { + mFragment = new PostFragment(); + Bundle bundle = new Bundle(); + bundle.putString(PostFragment.EXTRA_NAME, name); + bundle.putInt(PostFragment.EXTRA_POST_TYPE, postType); + bundle.putString(PostFragment.EXTRA_SORT_TYPE, sortType); + bundle.putInt(PostFragment.EXTRA_FILTER, filter); + bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + if(postType == PostDataSource.TYPE_USER) { + bundle.putString(PostFragment.EXTRA_USER_WHERE, getIntent().getStringExtra(EXTRA_USER_WHERE)); + } + if(postType == PostDataSource.TYPE_SEARCH) { + bundle.putString(PostFragment.EXTRA_QUERY, getIntent().getStringExtra(EXTRA_QUERY)); + } + mFragment.setArguments(bundle); + getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_filtered_posts_activity, mFragment).commit(); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.filtered_posts_activity, menu); + mMenu = menu; + MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_filtered_thing_activity); + if(isInLazyMode) { + lazyModeItem.setTitle(R.string.action_stop_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); + collapsingToolbarLayout.setLayoutParams(params); + } else { + lazyModeItem.setTitle(R.string.action_start_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); + collapsingToolbarLayout.setLayoutParams(params); + } + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + case R.id.action_sort_filtered_thing_activity: + switch (postType) { + case PostDataSource.TYPE_FRONT_PAGE: + bestSortTypeBottomSheetFragment.show(getSupportFragmentManager(), bestSortTypeBottomSheetFragment.getTag()); + break; + case PostDataSource.TYPE_SEARCH: + searchPostSortTypeBottomSheetFragment.show(getSupportFragmentManager(), searchPostSortTypeBottomSheetFragment.getTag()); + break; + case PostDataSource.TYPE_SUBREDDIT: + if(name.equals("popular") || name.equals("all")) { + popularAndAllSortTypeBottomSheetFragment.show(getSupportFragmentManager(), popularAndAllSortTypeBottomSheetFragment.getTag()); + } else { + subredditSortTypeBottomSheetFragment.show(getSupportFragmentManager(), subredditSortTypeBottomSheetFragment.getTag()); + } + break; + case PostDataSource.TYPE_USER: + userThingSortTypeBottomSheetFragment.show(getSupportFragmentManager(), userThingSortTypeBottomSheetFragment.getTag()); + } + return true; + case R.id.action_refresh_filtered_thing_activity: + if(mMenu != null) { + mMenu.findItem(R.id.action_lazy_mode_filtered_thing_activity).setTitle(R.string.action_start_lazy_mode); + } + if(mFragment instanceof FragmentCommunicator) { + ((FragmentCommunicator) mFragment).refresh(); + } + return true; + case R.id.action_lazy_mode_filtered_thing_activity: + MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_filtered_thing_activity); + if(isInLazyMode) { + ((FragmentCommunicator) mFragment).stopLazyMode(); + isInLazyMode = false; + lazyModeItem.setTitle(R.string.action_start_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); + collapsingToolbarLayout.setLayoutParams(params); + } else { + if(((FragmentCommunicator) mFragment).startLazyMode()) { + isInLazyMode = true; + lazyModeItem.setTitle(R.string.action_stop_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); + collapsingToolbarLayout.setLayoutParams(params); + } + } + return true; + } + return false; + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + if (mFragment != null) { + getSupportFragmentManager().putFragment(outState, FRAGMENT_OUT_STATE, mFragment); + } + outState.putBoolean(IS_IN_LAZY_MODE_STATE, isInLazyMode); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void searchSortTypeSelected(String sortType) { + ((PostFragment)mFragment).changeSortType(sortType); + } + + @Override + public void sortTypeSelected(String sortType) { + ((PostFragment)mFragment).changeSortType(sortType); + } + + @Override + public void userThingSortTypeSelected(String sortType) { + ((PostFragment)mFragment).changeSortType(sortType); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/LinkResolverActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/LinkResolverActivity.java new file mode 100644 index 00000000..c20d5ba9 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/LinkResolverActivity.java @@ -0,0 +1,215 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.browser.customtabs.CustomTabsIntent; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; +import static androidx.browser.customtabs.CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION; + +public class LinkResolverActivity extends AppCompatActivity { + + public static final String EXTRA_MESSAGE_FULLNAME = "ENF"; + public static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; + + private static final String POST_PATTERN = "/r/\\w+/comments/\\w+/{0,1}\\w+/{0,1}"; + private static final String COMMENT_PATTERN = "/r/\\w+/comments/\\w+/{0,1}\\w+/\\w+/{0,1}"; + private static final String SUBREDDIT_PATTERN = "/r/\\w+/{0,1}"; + private static final String USER_PATTERN_1 = "/user/\\w+/{0,1}"; + private static final String USER_PATTERN_2 = "/u/\\w+/{0,1}"; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + Uri uri = getIntent().getData(); + if(uri == null) { + Toast.makeText(this, R.string.no_link_available, Toast.LENGTH_SHORT).show(); + finish(); + } else { + String path = uri.getPath(); + if(path == null) { + deepLinkError(uri); + } else { + if(path.endsWith("/")) { + path = path.substring(0, path.length() - 1); + } + + String messageFullname = getIntent().getStringExtra(EXTRA_MESSAGE_FULLNAME); + String newAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); + + if(path.matches(POST_PATTERN)) { + List segments = uri.getPathSegments(); + int commentsIndex = segments.lastIndexOf("comments"); + if(commentsIndex >=0 && commentsIndex < segments.size() - 1) { + Intent intent = new Intent(this, ViewPostDetailActivity.class); + intent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, segments.get(commentsIndex + 1)); + intent.putExtra(ViewPostDetailActivity.EXTRA_MESSAGE_FULLNAME, messageFullname); + intent.putExtra(ViewPostDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); + startActivity(intent); + } else { + deepLinkError(uri); + } + } else if(path.matches(COMMENT_PATTERN)) { + List segments = uri.getPathSegments(); + int commentsIndex = segments.lastIndexOf("comments"); + if(commentsIndex >=0 && commentsIndex < segments.size() - 1) { + Intent intent = new Intent(this, ViewPostDetailActivity.class); + intent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, segments.get(commentsIndex + 1)); + intent.putExtra(ViewPostDetailActivity.EXTRA_SINGLE_COMMENT_ID, segments.get(segments.size() - 1)); + intent.putExtra(ViewPostDetailActivity.EXTRA_MESSAGE_FULLNAME, messageFullname); + intent.putExtra(ViewPostDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); + startActivity(intent); + } else { + deepLinkError(uri); + } + } else if(path.matches(SUBREDDIT_PATTERN)) { + String subredditName = path.substring(3); + if(subredditName.equals("popular") || subredditName.equals("all")) { + Intent intent = new Intent(this, MainActivity.class); + intent.putExtra(MainActivity.EXTRA_POST_TYPE, subredditName); + intent.putExtra(MainActivity.EXTRA_MESSSAGE_FULLNAME, messageFullname); + intent.putExtra(MainActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); + startActivity(intent); + } else { + Intent intent = new Intent(this, ViewSubredditDetailActivity.class); + intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, path.substring(3)); + intent.putExtra(ViewSubredditDetailActivity.EXTRA_MESSAGE_FULLNAME, messageFullname); + intent.putExtra(ViewSubredditDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); + startActivity(intent); + } + } else if(path.matches(USER_PATTERN_1)) { + Intent intent = new Intent(this, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, path.substring(6)); + intent.putExtra(ViewUserDetailActivity.EXTRA_MESSAGE_FULLNAME, messageFullname); + intent.putExtra(ViewUserDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); + startActivity(intent); + } else if(path.matches(USER_PATTERN_2)) { + Intent intent = new Intent(this, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, path.substring(3)); + intent.putExtra(ViewUserDetailActivity.EXTRA_MESSAGE_FULLNAME, messageFullname); + intent.putExtra(ViewUserDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); + startActivity(intent); + } else { + deepLinkError(uri); + } + } + + finish(); + } + } + + private void deepLinkError(Uri uri) { + PackageManager pm = getPackageManager(); + ArrayList resolveInfos = getCustomTabsPackages(pm); + if(!resolveInfos.isEmpty()) { + CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); + // add share action to menu list + builder.addDefaultShareMenuItem(); + builder.setToolbarColor(getResources().getColor(R.color.colorPrimary)); + CustomTabsIntent customTabsIntent = builder.build(); + customTabsIntent.intent.setPackage(resolveInfos.get(0).activityInfo.packageName); + if(uri.getScheme() == null) { + uri = Uri.parse("http://" + uri.toString()); + } + try { + customTabsIntent.launchUrl(this, uri); + } catch (ActivityNotFoundException e) { + openInBrowser(uri, pm); + } + } else { + openInBrowser(uri, pm); + } + } + + private ArrayList getCustomTabsPackages(PackageManager pm) { + // Get default VIEW intent handler. + Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.example.com")); + + // Get all apps that can handle VIEW intents. + List resolvedActivityList = pm.queryIntentActivities(activityIntent, 0); + ArrayList packagesSupportingCustomTabs = new ArrayList<>(); + for (ResolveInfo info : resolvedActivityList) { + Intent serviceIntent = new Intent(); + serviceIntent.setAction(ACTION_CUSTOM_TABS_CONNECTION); + serviceIntent.setPackage(info.activityInfo.packageName); + // Check if this package also resolves the Custom Tabs service. + if (pm.resolveService(serviceIntent, 0) != null) { + packagesSupportingCustomTabs.add(info); + } + } + return packagesSupportingCustomTabs; + } + + private void openInBrowser(Uri uri, PackageManager pm) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(uri); + + List activities = pm.queryIntentActivities(intent, 0); + ArrayList packageNames = new ArrayList<>(); + + String currentPackageName = getApplicationContext().getPackageName(); + + for(ResolveInfo info : activities) { + if(!info.activityInfo.packageName.equals(currentPackageName)) { + packageNames.add(info.activityInfo.packageName); + } + } + + if(!packageNames.isEmpty()) { + intent.setPackage(packageNames.get(0)); + startActivity(intent); + } else { + Toast.makeText(this, R.string.no_browser_found, Toast.LENGTH_SHORT).show(); + } + } + + public static Uri getRedditUriByPath(String path) { + return Uri.parse("https://www.reddit.com" + path); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/LoginActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/LoginActivity.java new file mode 100644 index 00000000..87a8e72b --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/LoginActivity.java @@ -0,0 +1,232 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.app.Activity; +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.view.MenuItem; +import android.webkit.CookieManager; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.FetchMyInfo; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.AsyncTask.ParseAndInsertNewAccountAsyncTask; +import ml.docilealligator.infinityforreddit.ParseAndSaveAccountInfo; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditAPI; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.RedditUtils; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class LoginActivity extends AppCompatActivity { + + @BindView(R.id.toolbar_login_activity) Toolbar toolbar; + + private String authCode; + + @Inject + @Named("no_oauth") + Retrofit mRetrofit; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_login); + + ButterKnife.bind(this); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + setSupportActionBar(toolbar); + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + WebView webView = findViewById(R.id.webview_login_activity); + webView.getSettings().setJavaScriptEnabled(true); + webView.getSettings().setDomStorageEnabled(true); + + Uri baseUri = Uri.parse(RedditUtils.OAUTH_URL); + Uri.Builder uriBuilder = baseUri.buildUpon(); + uriBuilder.appendQueryParameter(RedditUtils.CLIENT_ID_KEY, RedditUtils.CLIENT_ID); + uriBuilder.appendQueryParameter(RedditUtils.RESPONSE_TYPE_KEY, RedditUtils.RESPONSE_TYPE); + uriBuilder.appendQueryParameter(RedditUtils.STATE_KEY, RedditUtils.STATE); + uriBuilder.appendQueryParameter(RedditUtils.REDIRECT_URI_KEY, RedditUtils.REDIRECT_URI); + uriBuilder.appendQueryParameter(RedditUtils.DURATION_KEY, RedditUtils.DURATION); + uriBuilder.appendQueryParameter(RedditUtils.SCOPE_KEY, RedditUtils.SCOPE); + + String url = uriBuilder.toString(); + + CookieManager.getInstance().removeAllCookies(aBoolean -> {}); + + webView.loadUrl(url); + webView.setWebViewClient(new WebViewClient() { + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + if(url.contains("&code=") || url.contains("?code=")) { + Uri uri = Uri.parse(url); + String state = uri.getQueryParameter("state"); + if(state.equals(RedditUtils.STATE)) { + authCode = uri.getQueryParameter("code"); + + Map params = new HashMap<>(); + params.put(RedditUtils.GRANT_TYPE_KEY, "authorization_code"); + params.put("code", authCode); + params.put("redirect_uri", RedditUtils.REDIRECT_URI); + + RedditAPI api = mRetrofit.create(RedditAPI.class); + Call accessTokenCall = api.getAccessToken(RedditUtils.getHttpBasicAuthHeader(), params); + accessTokenCall.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if(response.isSuccessful()) { + try { + String accountResponse = response.body(); + if(accountResponse == null) { + //Handle error + return; + } + + JSONObject responseJSON = new JSONObject(accountResponse); + String accessToken = responseJSON.getString(RedditUtils.ACCESS_TOKEN_KEY); + String refreshToken = responseJSON.getString(RedditUtils.REFRESH_TOKEN_KEY); + + FetchMyInfo.fetchAccountInfo(mOauthRetrofit, accessToken, new FetchMyInfo.FetchUserMyListener() { + @Override + public void onFetchMyInfoSuccess(String response) { + ParseAndSaveAccountInfo.parseAndSaveAccountInfo(response, mRedditDataRoomDatabase, new ParseAndSaveAccountInfo.ParseAndSaveAccountInfoListener() { + @Override + public void onParseMyInfoSuccess(String name, String profileImageUrl, String bannerImageUrl, int karma) { + new ParseAndInsertNewAccountAsyncTask(name, accessToken, refreshToken, profileImageUrl, bannerImageUrl, + karma, authCode, mRedditDataRoomDatabase.accountDao(), + () -> { + Intent resultIntent = new Intent(); + setResult(Activity.RESULT_OK, resultIntent); + finish(); + }).execute(); + } + + @Override + public void onParseMyInfoFail() { + Toast.makeText(LoginActivity.this, R.string.parse_user_info_error, Toast.LENGTH_SHORT).show(); + finish(); + } + }); + } + + @Override + public void onFetchMyInfoFail() { + Toast.makeText(LoginActivity.this, R.string.cannot_fetch_user_info, Toast.LENGTH_SHORT).show(); + finish(); + } + }); + } catch (JSONException e) { + e.printStackTrace(); + Toast.makeText(LoginActivity.this, R.string.parse_json_response_error, Toast.LENGTH_SHORT).show(); + finish(); + } + } else { + Toast.makeText(LoginActivity.this, R.string.retrieve_token_error, Toast.LENGTH_SHORT).show(); + finish(); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + Toast.makeText(LoginActivity.this, R.string.retrieve_token_error, Toast.LENGTH_SHORT).show(); + finish(); + } + }); + } else { + Toast.makeText(LoginActivity.this, R.string.something_went_wrong, Toast.LENGTH_SHORT).show(); + finish(); + } + + } else if (url.contains("error=access_denied")) { + Toast.makeText(LoginActivity.this, R.string.access_denied, Toast.LENGTH_SHORT).show(); + finish(); + } else { + view.loadUrl(url); + } + + return true; + } + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + super.onPageStarted(view, url, favicon); + } + + @Override + public void onPageFinished(WebView view, String url) { + super.onPageFinished(view, url); + } + }); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + finish(); + return true; + } + return false; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java new file mode 100644 index 00000000..4e9345a1 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java @@ -0,0 +1,1247 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.app.Activity; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.ActionBarDrawerToggle; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.view.GravityCompat; +import androidx.core.widget.NestedScrollView; +import androidx.drawerlayout.widget.DrawerLayout; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager.widget.ViewPager; +import androidx.work.Constraints; +import androidx.work.ExistingPeriodicWorkPolicy; +import androidx.work.NetworkType; +import androidx.work.PeriodicWorkRequest; +import androidx.work.WorkManager; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.request.RequestOptions; +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.appbar.CollapsingToolbarLayout; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.google.android.material.tabs.TabLayout; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import java.util.ArrayList; +import java.util.concurrent.TimeUnit; + +import javax.inject.Inject; +import javax.inject.Named; + +import ml.docilealligator.infinityforreddit.Account.Account; +import ml.docilealligator.infinityforreddit.Account.AccountViewModel; +import ml.docilealligator.infinityforreddit.Adapter.AccountRecyclerViewAdapter; +import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; +import ml.docilealligator.infinityforreddit.Event.ChangeFontSizeEvent; +import ml.docilealligator.infinityforreddit.Event.ChangeNSFWEvent; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.FetchMyInfo; +import ml.docilealligator.infinityforreddit.FetchSubscribedThing; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.FragmentCommunicator; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.AsyncTask.InsertSubscribedThingsAsyncTask; +import ml.docilealligator.infinityforreddit.ParseAndSaveAccountInfo; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.Fragment.PostFragment; +import ml.docilealligator.infinityforreddit.Fragment.PostTypeBottomSheetFragment; +import ml.docilealligator.infinityforreddit.PullNotificationWorker; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.ReadMessage; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.Fragment.SortTypeBottomSheetFragment; +import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditData; +import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditData; +import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserData; +import butterknife.BindView; +import butterknife.ButterKnife; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import ml.docilealligator.infinityforreddit.AsyncTask.SwitchAccountAsyncTask; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.AsyncTask.SwitchToAnonymousAccountAsyncTask; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import pl.droidsonroids.gif.GifImageView; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class MainActivity extends AppCompatActivity implements SortTypeBottomSheetFragment.SortTypeSelectionCallback, + PostTypeBottomSheetFragment.PostTypeSelectionCallback { + + static final String EXTRA_POST_TYPE = "EPT"; + static final String EXTRA_MESSSAGE_FULLNAME = "ENF"; + static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; + + private static final String FETCH_USER_INFO_STATE = "FUIS"; + private static final String FETCH_SUBSCRIPTIONS_STATE = "FSS"; + private static final String DRAWER_ON_ACCOUNT_SWITCH_STATE = "DOASS"; + private static final String IS_IN_LAZY_MODE_STATE = "IILMS"; + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + private static final String ACCOUNT_NAME_STATE = "ANS"; + private static final String ACCOUNT_PROFILE_IMAGE_URL_STATE = "APIUS"; + private static final String ACCOUNT_BANNER_IMAGE_URL_STATE = "ABIUS"; + private static final String ACCOUNT_KARMA_STATE = "AKS"; + private static final String MESSAGE_FULLNAME_STATE = "MFS"; + private static final String NEW_ACCOUNT_NAME_STATE = "NANS"; + + private static final int LOGIN_ACTIVITY_REQUEST_CODE = 0; + + @BindView(R.id.drawer_layout) DrawerLayout drawer; + @BindView(R.id.coordinator_layout_main_activity) CoordinatorLayout coordinatorLayout; + @BindView(R.id.appbar_layout_main_activity) AppBarLayout appBarLayout; + @BindView(R.id.view_pager_main_activity) ViewPager viewPager; + @BindView(R.id.collapsing_toolbar_layout_main_activity) CollapsingToolbarLayout collapsingToolbarLayout; + @BindView(R.id.toolbar) Toolbar toolbar; + @BindView(R.id.nested_scroll_view_main_activity) NestedScrollView nestedScrollView; + @BindView(R.id.all_drawer_items_linear_layout_main_activity) LinearLayout allDrawerItemsLinearLayout; + @BindView(R.id.account_label_main_activity) TextView accountLabelTextView; + @BindView(R.id.profile_linear_layout_main_activity) LinearLayout profileLinearLayout; + @BindView(R.id.subscriptions_linear_layout_main_activity) LinearLayout subscriptionLinearLayout; + @BindView(R.id.inbox_linear_layout_main_activity) LinearLayout inboxLinearLayout; + @BindView(R.id.post_label_main_activity) TextView postLabelTextView; + @BindView(R.id.upvoted_linear_layout_main_activity) LinearLayout upvotedLinearLayout; + @BindView(R.id.downvoted_linear_layout_main_activity) LinearLayout downvotedLinearLayout; + @BindView(R.id.hidden_linear_layout_main_activity) LinearLayout hiddenLinearLayout; + @BindView(R.id.saved_linear_layout_main_activity) LinearLayout savedLinearLayout; + @BindView(R.id.gilded_linear_layout_main_activity) LinearLayout gildedLinearLayout; + @BindView(R.id.divider_main_activity) View divider; + @BindView(R.id.settings_linear_layout_main_activity) LinearLayout settingsLinearLayout; + @BindView(R.id.account_recycler_view_main_activity) RecyclerView accountRecyclerView; + @BindView(R.id.tab_layout_main_activity) TabLayout tabLayout; + @BindView(R.id.fab_main_activity) FloatingActionButton fab; + + private SectionsPagerAdapter sectionsPagerAdapter; + + private TextView mAccountNameTextView; + private TextView mKarmaTextView; + private GifImageView mProfileImageView; + private ImageView mBannerImageView; + private ImageView mDropIconImageView; + + private RequestManager glide; + private AppBarLayout.LayoutParams params; + private PostTypeBottomSheetFragment postTypeBottomSheetFragment; + private SortTypeBottomSheetFragment bestSortTypeBottomSheetFragment; + private SortTypeBottomSheetFragment popularAndAllSortTypeBottomSheetFragment; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String mAccountName; + private String mProfileImageUrl; + private String mBannerImageUrl; + private int mKarma; + private boolean mFetchUserInfoSuccess = false; + private boolean mFetchSubscriptionsSuccess = false; + private boolean mDrawerOnAccountSwitch = false; + private String mMessageFullname; + private String mNewAccountName; + + private Menu mMenu; + + private boolean isInLazyMode = false; + + AccountViewModel accountViewModel; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(R.style.AppTheme_NoActionBarWithTransparentStatusBar); + + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_main); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + Resources resources = getResources(); + + if(resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + + boolean lightNavBar = false; + if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + lightNavBar = true; + } + boolean finalLightNavBar = lightNavBar; + + View decorView = window.getDecorView(); + appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, State state) { + if(state == State.COLLAPSED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } else if(state == State.EXPANDED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } + } + }); + + int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (statusBarResourceId > 0) { + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); + params.topMargin = resources.getDimensionPixelSize(statusBarResourceId); + toolbar.setLayoutParams(params); + } + + int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); + if (navBarResourceId > 0) { + int navBarHeight = resources.getDimensionPixelSize(navBarResourceId); + CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) fab.getLayoutParams(); + params.bottomMargin = navBarHeight; + fab.setLayoutParams(params); + + nestedScrollView.setPadding(0, 0, 0, navBarHeight); + } + } + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + postTypeBottomSheetFragment = new PostTypeBottomSheetFragment(); + + bestSortTypeBottomSheetFragment = new SortTypeBottomSheetFragment(); + Bundle bestBundle = new Bundle(); + bestBundle.putBoolean(SortTypeBottomSheetFragment.EXTRA_NO_BEST_TYPE, false); + bestSortTypeBottomSheetFragment.setArguments(bestBundle); + + popularAndAllSortTypeBottomSheetFragment = new SortTypeBottomSheetFragment(); + Bundle popularBundle = new Bundle(); + popularBundle.putBoolean(SortTypeBottomSheetFragment.EXTRA_NO_BEST_TYPE, true); + popularAndAllSortTypeBottomSheetFragment.setArguments(popularBundle); + + setSupportActionBar(toolbar); + + drawer = findViewById(R.id.drawer_layout); + ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( + this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); + drawer.addDrawerListener(toggle); + toggle.syncState(); + + params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); + + if(savedInstanceState != null) { + mFetchUserInfoSuccess = savedInstanceState.getBoolean(FETCH_USER_INFO_STATE); + mFetchSubscriptionsSuccess = savedInstanceState.getBoolean(FETCH_SUBSCRIPTIONS_STATE); + mDrawerOnAccountSwitch = savedInstanceState.getBoolean(DRAWER_ON_ACCOUNT_SWITCH_STATE); + isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); + mProfileImageUrl = savedInstanceState.getString(ACCOUNT_PROFILE_IMAGE_URL_STATE); + mBannerImageUrl = savedInstanceState.getString(ACCOUNT_BANNER_IMAGE_URL_STATE); + mKarma = savedInstanceState.getInt(ACCOUNT_KARMA_STATE); + mMessageFullname = savedInstanceState.getString(MESSAGE_FULLNAME_STATE); + mNewAccountName = savedInstanceState.getString(NEW_ACCOUNT_NAME_STATE); + + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccountAndBindView(); + } else { + bindView(); + } + } else { + mMessageFullname = getIntent().getStringExtra(EXTRA_MESSSAGE_FULLNAME); + mNewAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); + getCurrentAccountAndBindView(); + } + + fab.setOnClickListener(view -> { + if(mAccessToken == null) { + Toast.makeText(MainActivity.this, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + postTypeBottomSheetFragment.show(getSupportFragmentManager(), postTypeBottomSheetFragment.getTag()); + }); + } + + private void getCurrentAccountAndBindView() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + boolean enableNotification = mSharedPreferences.getBoolean(SharedPreferencesUtils.ENABLE_NOTIFICATION_KEY, true); + String notificationInterval = mSharedPreferences.getString(SharedPreferencesUtils.NOTIFICATION_INTERVAL_KEY, "1"); + + WorkManager workManager = WorkManager.getInstance(this); + + if(mNewAccountName != null) { + if(account == null || !account.getUsername().equals(mNewAccountName)) { + new SwitchAccountAsyncTask(mRedditDataRoomDatabase, mNewAccountName, newAccount -> { + EventBus.getDefault().post(new SwitchAccountEvent(getClass().getName())); + Toast.makeText(this, R.string.account_switched, Toast.LENGTH_SHORT).show(); + + mNewAccountName = null; + if(newAccount == null) { + mNullAccessToken = true; + + if(mMenu != null) { + mMenu.findItem(R.id.action_subscriptions_main_activity).setVisible(false); + } + } else { + mAccessToken = newAccount.getAccessToken(); + mAccountName = newAccount.getUsername(); + mProfileImageUrl = newAccount.getProfileImageUrl(); + mBannerImageUrl = newAccount.getBannerImageUrl(); + mKarma = newAccount.getKarma(); + + if(mMenu != null) { + mMenu.findItem(R.id.action_subscriptions_main_activity).setVisible(true); + } + } + + if(enableNotification) { + Constraints constraints = new Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build(); + + PeriodicWorkRequest pullNotificationRequest = + new PeriodicWorkRequest.Builder(PullNotificationWorker.class, + Long.parseLong(notificationInterval), TimeUnit.HOURS) + .setConstraints(constraints) + .build(); + + workManager.enqueueUniquePeriodicWork(PullNotificationWorker.WORKER_TAG, + ExistingPeriodicWorkPolicy.KEEP, pullNotificationRequest); + } else { + workManager.cancelUniqueWork(PullNotificationWorker.WORKER_TAG); + } + + bindView(); + }).execute(); + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + mProfileImageUrl = account.getProfileImageUrl(); + mBannerImageUrl = account.getBannerImageUrl(); + mKarma = account.getKarma(); + + if(mMenu != null) { + mMenu.findItem(R.id.action_subscriptions_main_activity).setVisible(true); + } + + if(enableNotification) { + Constraints constraints = new Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build(); + + PeriodicWorkRequest pullNotificationRequest = + new PeriodicWorkRequest.Builder(PullNotificationWorker.class, + Long.parseLong(notificationInterval), TimeUnit.HOURS) + .setConstraints(constraints) + .build(); + + workManager.enqueueUniquePeriodicWork(PullNotificationWorker.WORKER_TAG, + ExistingPeriodicWorkPolicy.KEEP, pullNotificationRequest); + } else { + workManager.cancelUniqueWork(PullNotificationWorker.WORKER_TAG); + } + + bindView(); + } + } else { + if(account == null) { + mNullAccessToken = true; + + if(mMenu != null) { + mMenu.findItem(R.id.action_subscriptions_main_activity).setVisible(false); + } + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + mProfileImageUrl = account.getProfileImageUrl(); + mBannerImageUrl = account.getBannerImageUrl(); + mKarma = account.getKarma(); + + if(mMenu != null) { + mMenu.findItem(R.id.action_subscriptions_main_activity).setVisible(true); + } + } + + if(enableNotification) { + Constraints constraints = new Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build(); + + PeriodicWorkRequest pullNotificationRequest = + new PeriodicWorkRequest.Builder(PullNotificationWorker.class, + Long.parseLong(notificationInterval), TimeUnit.HOURS) + .setConstraints(constraints) + .build(); + + workManager.enqueueUniquePeriodicWork(PullNotificationWorker.WORKER_TAG, + ExistingPeriodicWorkPolicy.KEEP, pullNotificationRequest); + } else { + workManager.cancelUniqueWork(PullNotificationWorker.WORKER_TAG); + } + + bindView(); + } + }).execute(); + } + + private void bindView() { + if(isDestroyed()) { + return; + } + + sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); + viewPager.setAdapter(sectionsPagerAdapter); + viewPager.setOffscreenPageLimit(3); + tabLayout.setupWithViewPager(viewPager); + + viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {} + + @Override + public void onPageSelected(int position) { + fab.show(); + if(isInLazyMode) { + if(position == sectionsPagerAdapter.getCurrentLazyModeFragmentPosition()) { + sectionsPagerAdapter.resumeLazyMode(); + } else { + sectionsPagerAdapter.pauseLazyMode(); + } + } + } + + @Override + public void onPageScrollStateChanged(int state) {} + }); + + loadSubscriptions(); + + glide = Glide.with(this); + + AccountRecyclerViewAdapter adapter = new AccountRecyclerViewAdapter(this, glide, mAccountName, + new AccountRecyclerViewAdapter.ItemSelectedListener() { + @Override + public void accountSelected(Account account) { + new SwitchAccountAsyncTask(mRedditDataRoomDatabase, account.getUsername(), newAccount -> { + Intent intent = new Intent(MainActivity.this, MainActivity.class); + startActivity(intent); + finish(); + }).execute(); + } + + @Override + public void addAccountSelected() { + Intent intent = new Intent(MainActivity.this, LoginActivity.class); + startActivityForResult(intent, LOGIN_ACTIVITY_REQUEST_CODE); + } + + @Override + public void anonymousSelected() { + new SwitchToAnonymousAccountAsyncTask(mRedditDataRoomDatabase, false, + () -> { + Intent intent = new Intent(MainActivity.this, MainActivity.class); + startActivity(intent); + finish(); + }).execute(); + } + + @Override + public void logoutSelected() { + new SwitchToAnonymousAccountAsyncTask(mRedditDataRoomDatabase, true, + () -> { + Intent intent = new Intent(MainActivity.this, MainActivity.class); + startActivity(intent); + finish(); + }).execute(); + } + }); + + accountRecyclerView.setLayoutManager(new LinearLayoutManager(this)); + accountRecyclerView.setNestedScrollingEnabled(false); + accountRecyclerView.setAdapter(adapter); + + accountViewModel = new ViewModelProvider(this, + new AccountViewModel.Factory(getApplication(), mRedditDataRoomDatabase, mAccountName)).get(AccountViewModel.class); + accountViewModel.getAccountsExceptCurrentAccountLiveData().observe(this, adapter::changeAccountsDataset); + + if(getIntent().hasExtra(EXTRA_POST_TYPE)) { + String type = getIntent().getStringExtra(EXTRA_POST_TYPE); + if(type != null && type.equals("popular")) { + viewPager.setCurrentItem(1); + } else { + viewPager.setCurrentItem(2); + } + } + + View header = findViewById(R.id.nav_header_main_activity); + mAccountNameTextView = header.findViewById(R.id.name_text_view_nav_header_main); + mKarmaTextView = header.findViewById(R.id.karma_text_view_nav_header_main); + mProfileImageView = header.findViewById(R.id.profile_image_view_nav_header_main); + mBannerImageView = header.findViewById(R.id.banner_image_view_nav_header_main); + mDropIconImageView = header.findViewById(R.id.account_switcher_image_view_nav_header_main); + + if(mDrawerOnAccountSwitch) { + mDropIconImageView.setImageDrawable(getResources().getDrawable(R.drawable.ic_baseline_arrow_drop_up_24px)); + accountRecyclerView.setVisibility(View.VISIBLE); + allDrawerItemsLinearLayout.setVisibility(View.GONE); + } else { + mDropIconImageView.setImageDrawable(getResources().getDrawable(R.drawable.ic_baseline_arrow_drop_down_24px)); + accountRecyclerView.setVisibility(View.GONE); + allDrawerItemsLinearLayout.setVisibility(View.VISIBLE); + } + + header.setOnClickListener(view -> { + if(mDrawerOnAccountSwitch) { + mDrawerOnAccountSwitch = false; + mDropIconImageView.setImageDrawable(getResources().getDrawable(R.drawable.ic_baseline_arrow_drop_down_24px)); + accountRecyclerView.setVisibility(View.GONE); + allDrawerItemsLinearLayout.setVisibility(View.VISIBLE); + } else { + mDrawerOnAccountSwitch = true; + mDropIconImageView.setImageDrawable(getResources().getDrawable(R.drawable.ic_baseline_arrow_drop_up_24px)); + accountRecyclerView.setVisibility(View.VISIBLE); + allDrawerItemsLinearLayout.setVisibility(View.GONE); + } + }); + + loadUserData(); + + if(mAccessToken != null) { + mKarmaTextView.setText(getString(R.string.karma_info, mKarma)); + mAccountNameTextView.setText(mAccountName); + if(mMessageFullname != null) { + ReadMessage.readMessage(mOauthRetrofit, mAccessToken, mMessageFullname, new ReadMessage.ReadMessageListener() { + @Override + public void readSuccess() { + mMessageFullname = null; + } + + @Override + public void readFailed() { + + } + }); + } + } else { + mKarmaTextView.setText(R.string.press_here_to_login); + mAccountNameTextView.setText(R.string.anonymous_account); + accountLabelTextView.setVisibility(View.GONE); + profileLinearLayout.setVisibility(View.GONE); + subscriptionLinearLayout.setVisibility(View.GONE); + inboxLinearLayout.setVisibility(View.GONE); + postLabelTextView.setVisibility(View.GONE); + upvotedLinearLayout.setVisibility(View.GONE); + downvotedLinearLayout.setVisibility(View.GONE); + hiddenLinearLayout.setVisibility(View.GONE); + savedLinearLayout.setVisibility(View.GONE); + gildedLinearLayout.setVisibility(View.GONE); + divider.setVisibility(View.GONE); + } + + if (mProfileImageUrl != null && !mProfileImageUrl.equals("")) { + glide.load(mProfileImageUrl) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(144, 0))) + .error(glide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(144, 0)))) + .into(mProfileImageView); + } else { + glide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(144, 0))) + .into(mProfileImageView); + } + + if (mBannerImageUrl != null && !mBannerImageUrl.equals("")) { + glide.load(mBannerImageUrl).into(mBannerImageView); + } + + profileLinearLayout.setOnClickListener(view -> { + Intent intent = new Intent(this, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mAccountName); + startActivity(intent); + drawer.closeDrawers(); + }); + + subscriptionLinearLayout.setOnClickListener(view -> { + Intent intent = new Intent(this, SubscribedThingListingActivity.class); + startActivity(intent); + drawer.closeDrawers(); + }); + + inboxLinearLayout.setOnClickListener(view -> { + Intent intent = new Intent(this, ViewMessageActivity.class); + startActivity(intent); + drawer.closeDrawers(); + }); + + upvotedLinearLayout.setOnClickListener(view -> { + Intent intent = new Intent(MainActivity.this, AccountPostsActivity.class); + intent.putExtra(AccountPostsActivity.EXTRA_USER_WHERE, PostDataSource.USER_WHERE_UPVOTED); + startActivity(intent); + drawer.closeDrawers(); + }); + + downvotedLinearLayout.setOnClickListener(view -> { + Intent intent = new Intent(MainActivity.this, AccountPostsActivity.class); + intent.putExtra(AccountPostsActivity.EXTRA_USER_WHERE, PostDataSource.USER_WHERE_DOWNVOTED); + startActivity(intent); + drawer.closeDrawers(); + }); + + hiddenLinearLayout.setOnClickListener(view -> { + Intent intent = new Intent(MainActivity.this, AccountPostsActivity.class); + intent.putExtra(AccountPostsActivity.EXTRA_USER_WHERE, PostDataSource.USER_WHERE_HIDDEN); + startActivity(intent); + drawer.closeDrawers(); + }); + + savedLinearLayout.setOnClickListener(view -> { + Intent intent = new Intent(MainActivity.this, AccountSavedThingActivity.class); + startActivity(intent); + drawer.closeDrawers(); + }); + + gildedLinearLayout.setOnClickListener(view -> { + Intent intent = new Intent(MainActivity.this, AccountPostsActivity.class); + intent.putExtra(AccountPostsActivity.EXTRA_USER_WHERE, PostDataSource.USER_WHERE_GILDED); + startActivity(intent); + drawer.closeDrawers(); + }); + + settingsLinearLayout.setOnClickListener(view -> { + drawer.closeDrawers(); + Intent intent = new Intent(MainActivity.this, SettingsActivity.class); + startActivity(intent); + }); + } + + private void loadSubscriptions() { + if (mAccessToken != null && !mFetchSubscriptionsSuccess) { + FetchSubscribedThing.fetchSubscribedThing(mOauthRetrofit, mAccessToken, mAccountName, null, + new ArrayList<>(), new ArrayList<>(), + new ArrayList<>(), + new FetchSubscribedThing.FetchSubscribedThingListener() { + @Override + public void onFetchSubscribedThingSuccess(ArrayList subscribedSubredditData, + ArrayList subscribedUserData, + ArrayList subredditData) { + new InsertSubscribedThingsAsyncTask( + mRedditDataRoomDatabase, + mAccountName, + subscribedSubredditData, + subscribedUserData, + subredditData, + () -> mFetchSubscriptionsSuccess = true).execute(); + } + + @Override + public void onFetchSubscribedThingFail() { + mFetchSubscriptionsSuccess = false; + } + }); + } + } + + private void loadUserData() { + if (!mFetchUserInfoSuccess) { + FetchMyInfo.fetchAccountInfo(mOauthRetrofit, mAccessToken, new FetchMyInfo.FetchUserMyListener() { + @Override + public void onFetchMyInfoSuccess(String response) { + ParseAndSaveAccountInfo.parseAndSaveAccountInfo(response, mRedditDataRoomDatabase, new ParseAndSaveAccountInfo.ParseAndSaveAccountInfoListener() { + @Override + public void onParseMyInfoSuccess(String name, String profileImageUrl, String bannerImageUrl, int karma) { + mAccountNameTextView.setText(name); + if (profileImageUrl != null && !profileImageUrl.equals("")) { + glide.load(profileImageUrl) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0))) + .error(glide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0)))) + .into(mProfileImageView); + } else { + glide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0))) + .into(mProfileImageView); + } + if (bannerImageUrl != null && !bannerImageUrl.equals("")) { + glide.load(bannerImageUrl).into(mBannerImageView); + } + + mAccountName = name; + mProfileImageUrl = profileImageUrl; + mBannerImageUrl = bannerImageUrl; + mKarma = karma; + + mKarmaTextView.setText(getString(R.string.karma_info, karma)); + + mFetchUserInfoSuccess = true; + } + + @Override + public void onParseMyInfoFail() { + mFetchUserInfoSuccess = false; + } + }); + } + + @Override + public void onFetchMyInfoFail() { + mFetchUserInfoSuccess = false; + } + }); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if(requestCode == LOGIN_ACTIVITY_REQUEST_CODE && resultCode == Activity.RESULT_OK) { + Intent intent = new Intent(this, MainActivity.class); + startActivity(intent); + finish(); + } + + super.onActivityResult(requestCode, resultCode, data); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.main_activity, menu); + mMenu = menu; + MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_main_activity); + MenuItem subscriptionsItem = mMenu.findItem(R.id.action_subscriptions_main_activity); + + if(mAccessToken != null) { + subscriptionsItem.setVisible(true); + } else { + subscriptionsItem.setVisible(false); + } + + if(isInLazyMode) { + lazyModeItem.setTitle(R.string.action_stop_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); + collapsingToolbarLayout.setLayoutParams(params); + } else { + lazyModeItem.setTitle(R.string.action_start_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); + collapsingToolbarLayout.setLayoutParams(params); + } + + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case R.id.action_subscriptions_main_activity: + Intent subscriptionsIntent = new Intent(this, SubscribedThingListingActivity.class); + startActivity(subscriptionsIntent); + return true; + case R.id.action_sort_main_activity: + if(viewPager.getCurrentItem() == 1 ||viewPager.getCurrentItem() == 2) { + popularAndAllSortTypeBottomSheetFragment.show(getSupportFragmentManager(), popularAndAllSortTypeBottomSheetFragment.getTag()); + } else { + bestSortTypeBottomSheetFragment.show(getSupportFragmentManager(), bestSortTypeBottomSheetFragment.getTag()); + } + return true; + case R.id.action_search_main_activity: + Intent intent = new Intent(this, SearchActivity.class); + intent.putExtra(SearchActivity.EXTRA_SEARCH_ONLY_SUBREDDITS, false); + startActivity(intent); + return true; + case R.id.action_refresh_main_activity: + if(mMenu != null) { + mMenu.findItem(R.id.action_lazy_mode_main_activity).setTitle(R.string.action_start_lazy_mode); + } + sectionsPagerAdapter.refresh(); + mFetchUserInfoSuccess = false; + loadUserData(); + return true; + case R.id.action_lazy_mode_main_activity: + MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_main_activity); + if(isInLazyMode) { + sectionsPagerAdapter.stopLazyMode(); + isInLazyMode = false; + lazyModeItem.setTitle(R.string.action_start_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); + collapsingToolbarLayout.setLayoutParams(params); + } else { + if(sectionsPagerAdapter.startLazyMode()) { + isInLazyMode = true; + lazyModeItem.setTitle(R.string.action_stop_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); + collapsingToolbarLayout.setLayoutParams(params); + } + } + return true; + } + return false; + } + + @Override + public void onBackPressed() { + DrawerLayout drawer = findViewById(R.id.drawer_layout); + if (drawer.isDrawerOpen(GravityCompat.START)) { + drawer.closeDrawer(GravityCompat.START); + } else { + super.onBackPressed(); + } + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(FETCH_USER_INFO_STATE, mFetchUserInfoSuccess); + outState.putBoolean(FETCH_SUBSCRIPTIONS_STATE, mFetchSubscriptionsSuccess); + outState.putBoolean(DRAWER_ON_ACCOUNT_SWITCH_STATE, mDrawerOnAccountSwitch); + outState.putBoolean(IS_IN_LAZY_MODE_STATE, isInLazyMode); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putString(ACCOUNT_NAME_STATE, mAccountName); + outState.putString(ACCOUNT_PROFILE_IMAGE_URL_STATE, mProfileImageUrl); + outState.putString(ACCOUNT_BANNER_IMAGE_URL_STATE, mBannerImageUrl); + outState.putInt(ACCOUNT_KARMA_STATE, mKarma); + outState.putString(MESSAGE_FULLNAME_STATE, mMessageFullname); + outState.putString(NEW_ACCOUNT_NAME_STATE, mNewAccountName); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void sortTypeSelected(String sortType) { + sectionsPagerAdapter.changeSortType(sortType); + } + + @Override + public void postTypeSelected(int postType) { + Intent intent; + switch (postType) { + case PostTypeBottomSheetFragment.TYPE_TEXT: + intent = new Intent(MainActivity.this, PostTextActivity.class); + startActivity(intent); + break; + case PostTypeBottomSheetFragment.TYPE_LINK: + intent = new Intent(MainActivity.this, PostLinkActivity.class); + startActivity(intent); + break; + case PostTypeBottomSheetFragment.TYPE_IMAGE: + intent = new Intent(MainActivity.this, PostImageActivity.class); + startActivity(intent); + break; + case PostTypeBottomSheetFragment.TYPE_VIDEO: + intent = new Intent(MainActivity.this, PostVideoActivity.class); + startActivity(intent); + } + } + + public void postScrollUp() { + fab.show(); + } + + public void postScrollDown() { + fab.hide(); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + if(!getClass().getName().equals(event.excludeActivityClassName)) { + finish(); + } + } + + @Subscribe + public void onChangeNSFWEvent(ChangeNSFWEvent changeNSFWEvent) { + sectionsPagerAdapter.changeNSFW(changeNSFWEvent.nsfw); + } + + @Subscribe + public void onChangeFontSizeEvent(ChangeFontSizeEvent changeFontSizeEvent) { + recreate(); + } + + private class SectionsPagerAdapter extends FragmentPagerAdapter { + private PostFragment frontPagePostFragment; + private PostFragment popularPostFragment; + private PostFragment allPostFragment; + + SectionsPagerAdapter(FragmentManager fm) { + super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); + } + + @NonNull + @Override + public Fragment getItem(int position) { + if(mAccessToken == null) { + if(position == 0) { + PostFragment fragment = new PostFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); + bundle.putString(PostFragment.EXTRA_NAME, "popular"); + bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_HOT); + bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); + bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + fragment.setArguments(bundle); + return fragment; + } else { + PostFragment fragment = new PostFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); + bundle.putString(PostFragment.EXTRA_NAME, "all"); + bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_HOT); + bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); + bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + fragment.setArguments(bundle); + return fragment; + } + } + + if (position == 0) { + PostFragment fragment = new PostFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_FRONT_PAGE); + bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_BEST); + bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); + bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + fragment.setArguments(bundle); + return fragment; + } else if(position == 1) { + PostFragment fragment = new PostFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); + bundle.putString(PostFragment.EXTRA_NAME, "popular"); + bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_HOT); + bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); + bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + fragment.setArguments(bundle); + return fragment; + } else { + PostFragment fragment = new PostFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); + bundle.putString(PostFragment.EXTRA_NAME, "all"); + bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_HOT); + bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); + bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + fragment.setArguments(bundle); + return fragment; + } + } + + @Override + public int getCount() + { + if(mAccessToken == null) { + return 2; + } + return 3; + } + + @Override + public CharSequence getPageTitle(int position) { + if(mAccessToken == null) { + switch (position) { + case 0: + return "Popular"; + case 1: + return "All"; + } + } else { + switch (position) { + case 0: + return "Best"; + case 1: + return "Popular"; + case 2: + return "All"; + } + } + return null; + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + Fragment fragment = (Fragment) super.instantiateItem(container, position); + if(mAccessToken == null) { + switch (position) { + case 0: + popularPostFragment = (PostFragment) fragment; + break; + case 1: + allPostFragment = (PostFragment) fragment; + } + } else { + switch (position) { + case 0: + frontPagePostFragment = (PostFragment) fragment; + break; + case 1: + popularPostFragment = (PostFragment) fragment; + break; + case 2: + allPostFragment = (PostFragment) fragment; + } + } + return fragment; + } + + boolean startLazyMode() { + if(mAccessToken == null) { + switch (viewPager.getCurrentItem()) { + case 0: + return ((FragmentCommunicator) popularPostFragment).startLazyMode(); + case 1: + return ((FragmentCommunicator) allPostFragment).startLazyMode(); + } + } else { + switch (viewPager.getCurrentItem()) { + case 0: + return ((FragmentCommunicator) frontPagePostFragment).startLazyMode(); + case 1: + return ((FragmentCommunicator) popularPostFragment).startLazyMode(); + case 2: + return ((FragmentCommunicator) allPostFragment).startLazyMode(); + } + } + + return false; + } + + void stopLazyMode() { + if(mAccessToken == null) { + switch (getCurrentLazyModeFragmentPosition()) { + case 0: + ((FragmentCommunicator) popularPostFragment).stopLazyMode(); + break; + case 1: + ((FragmentCommunicator) allPostFragment).stopLazyMode(); + break; + } + } else { + switch (getCurrentLazyModeFragmentPosition()) { + case 0: + ((FragmentCommunicator) frontPagePostFragment).stopLazyMode(); + break; + case 1: + ((FragmentCommunicator) popularPostFragment).stopLazyMode(); + break; + case 2: + ((FragmentCommunicator) allPostFragment).stopLazyMode(); + break; + } + } + } + + void resumeLazyMode() { + if(mAccessToken == null) { + switch (getCurrentLazyModeFragmentPosition()) { + case 0: + ((FragmentCommunicator) popularPostFragment).resumeLazyMode(false); + break; + case 1: + ((FragmentCommunicator) allPostFragment).resumeLazyMode(false); + break; + } + } else { + switch (getCurrentLazyModeFragmentPosition()) { + case 0: + ((FragmentCommunicator) frontPagePostFragment).resumeLazyMode(false); + break; + case 1: + ((FragmentCommunicator) popularPostFragment).resumeLazyMode(false); + break; + case 2: + ((FragmentCommunicator) allPostFragment).resumeLazyMode(false); + break; + } + } + } + + void pauseLazyMode() { + if(mAccessToken == null) { + switch (getCurrentLazyModeFragmentPosition()) { + case 0: + ((FragmentCommunicator) popularPostFragment).pauseLazyMode(false); + break; + case 1: + ((FragmentCommunicator) allPostFragment).pauseLazyMode(false); + } + } else { + switch (getCurrentLazyModeFragmentPosition()) { + case 0: + ((FragmentCommunicator) frontPagePostFragment).pauseLazyMode(false); + break; + case 1: + ((FragmentCommunicator) popularPostFragment).pauseLazyMode(false); + break; + case 2: + ((FragmentCommunicator) allPostFragment).pauseLazyMode(false); + } + } + } + + int getCurrentLazyModeFragmentPosition() { + if(mAccessToken == null) { + if(!isInLazyMode) { + return -1; + } else if(popularPostFragment != null && ((FragmentCommunicator) popularPostFragment).isInLazyMode()) { + return 0; + } else if(allPostFragment != null && ((FragmentCommunicator) allPostFragment).isInLazyMode()) { + return 1; + } else { + return -1; + } + } else { + if(!isInLazyMode) { + return -1; + } else if(frontPagePostFragment != null && ((FragmentCommunicator) frontPagePostFragment).isInLazyMode()) { + return 0; + } else if(popularPostFragment != null && ((FragmentCommunicator) popularPostFragment).isInLazyMode()) { + return 1; + } else if(allPostFragment != null && ((FragmentCommunicator) allPostFragment).isInLazyMode()) { + return 2; + } else { + return -1; + } + } + } + + void changeSortType(String sortType) { + if(mAccessToken == null) { + if(viewPager.getCurrentItem() == 0) { + popularPostFragment.changeSortType(sortType); + } else { + allPostFragment.changeSortType(sortType); + } + } else { + switch (viewPager.getCurrentItem()) { + case 0: + frontPagePostFragment.changeSortType(sortType); + break; + case 1: + popularPostFragment.changeSortType(sortType); + break; + case 2: + allPostFragment.changeSortType(sortType); + } + } + } + + public void refresh() { + if(mAccessToken == null) { + if(viewPager.getCurrentItem() == 0) { + if(popularPostFragment != null) { + ((FragmentCommunicator) popularPostFragment).refresh(); + } + } else { + if(allPostFragment != null) { + ((FragmentCommunicator) allPostFragment).refresh(); + } + } + } else { + switch (viewPager.getCurrentItem()) { + case 0: + if(frontPagePostFragment != null) { + ((FragmentCommunicator) frontPagePostFragment).refresh(); + } + break; + case 1: + if(popularPostFragment != null) { + ((FragmentCommunicator) popularPostFragment).refresh(); + } + break; + case 2: + if(allPostFragment != null) { + ((FragmentCommunicator) allPostFragment).refresh(); + } + } + } + } + + void changeNSFW(boolean nsfw) { + if(frontPagePostFragment != null) { + frontPagePostFragment.changeNSFW(nsfw); + } + if(popularPostFragment != null) { + popularPostFragment.changeNSFW(nsfw); + } + if(allPostFragment != null) { + allPostFragment.changeNSFW(nsfw); + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostImageActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostImageActivity.java new file mode 100644 index 00000000..6320380a --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostImageActivity.java @@ -0,0 +1,600 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Environment; +import android.provider.MediaStore; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.content.ContextCompat; +import androidx.core.content.FileProvider; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.request.RequestOptions; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.google.android.material.snackbar.Snackbar; +import com.libRG.CustomTextView; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import java.io.File; +import java.io.IOException; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.AsyncTask.LoadSubredditIconAsyncTask; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.Event.SubmitImagePostEvent; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.Flair; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.Fragment.FlairBottomSheetFragment; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.SubmitPostService; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import pl.droidsonroids.gif.GifImageView; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class PostImageActivity extends AppCompatActivity implements FlairBottomSheetFragment.FlairSelectionCallback { + + static final String EXTRA_SUBREDDIT_NAME = "ESN"; + + private static final String SUBREDDIT_NAME_STATE = "SNS"; + private static final String SUBREDDIT_ICON_STATE = "SIS"; + private static final String SUBREDDIT_SELECTED_STATE = "SSS"; + private static final String SUBREDDIT_IS_USER_STATE = "SIUS"; + private static final String IMAGE_URI_STATE = "IUS"; + private static final String LOAD_SUBREDDIT_ICON_STATE = "LSIS"; + private static final String IS_POSTING_STATE = "IPS"; + private static final String FLAIR_STATE = "FS"; + private static final String IS_SPOILER_STATE = "ISS"; + private static final String IS_NSFW_STATE = "INS"; + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + private static final String ACCOUNT_NAME_STATE = "ANS"; + + private static final int SUBREDDIT_SELECTION_REQUEST_CODE = 0; + private static final int PICK_IMAGE_REQUEST_CODE = 1; + private static final int CAPTURE_IMAGE_REQUEST_CODE = 2; + + @BindView(R.id.coordinator_layout_post_image_activity) CoordinatorLayout coordinatorLayout; + @BindView(R.id.toolbar_post_image_activity) Toolbar toolbar; + @BindView(R.id.subreddit_icon_gif_image_view_post_image_activity) GifImageView iconGifImageView; + @BindView(R.id.subreddit_name_text_view_post_image_activity) TextView subredditNameTextView; + @BindView(R.id.rules_button_post_image_activity) Button rulesButton; + @BindView(R.id.flair_custom_text_view_post_image_activity) CustomTextView flairTextView; + @BindView(R.id.spoiler_custom_text_view_post_image_activity) CustomTextView spoilerTextView; + @BindView(R.id.nsfw_custom_text_view_post_image_activity) CustomTextView nsfwTextView; + @BindView(R.id.post_title_edit_text_post_image_activity) EditText titleEditText; + @BindView(R.id.select_image_constraint_layout_post_image_activity) ConstraintLayout constraintLayout; + @BindView(R.id.capture_fab_post_image_activity) FloatingActionButton captureFab; + @BindView(R.id.select_from_library_fab_post_image_activity) FloatingActionButton selectFromLibraryFab; + @BindView(R.id.select_again_text_view_post_image_activity) TextView selectAgainTextView; + @BindView(R.id.image_view_post_image_activity) ImageView imageView; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String mAccountName; + private String iconUrl; + private String subredditName; + private boolean subredditSelected = false; + private boolean subredditIsUser; + private boolean loadSubredditIconSuccessful = true; + private boolean isPosting; + private Uri imageUri; + + private Flair flair; + private boolean isSpoiler = false; + private boolean isNSFW = false; + + private Menu mMemu; + private RequestManager mGlide; + private FlairBottomSheetFragment flairSelectionBottomSheetFragment; + private Snackbar mPostingSnackbar; + + @Inject + @Named("no_oauth") + Retrofit mRetrofit; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + @Named("upload_media") + Retrofit mUploadMediaRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_post_image); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Window window = getWindow(); + if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + mGlide = Glide.with(this); + + mPostingSnackbar = Snackbar.make(coordinatorLayout, R.string.posting, Snackbar.LENGTH_INDEFINITE); + + if(savedInstanceState != null) { + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); + + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccount(); + } + + subredditName = savedInstanceState.getString(SUBREDDIT_NAME_STATE); + iconUrl = savedInstanceState.getString(SUBREDDIT_ICON_STATE); + subredditSelected = savedInstanceState.getBoolean(SUBREDDIT_SELECTED_STATE); + subredditIsUser = savedInstanceState.getBoolean(SUBREDDIT_IS_USER_STATE); + loadSubredditIconSuccessful = savedInstanceState.getBoolean(LOAD_SUBREDDIT_ICON_STATE); + isPosting = savedInstanceState.getBoolean(IS_POSTING_STATE); + flair = savedInstanceState.getParcelable(FLAIR_STATE); + isSpoiler = savedInstanceState.getBoolean(IS_SPOILER_STATE); + isNSFW = savedInstanceState.getBoolean(IS_NSFW_STATE); + + if(savedInstanceState.getString(IMAGE_URI_STATE) != null) { + imageUri = Uri.parse(savedInstanceState.getString(IMAGE_URI_STATE)); + loadImage(); + } + + if(subredditName != null) { + subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); + subredditNameTextView.setText(subredditName); + flairTextView.setVisibility(View.VISIBLE); + if(!loadSubredditIconSuccessful) { + loadSubredditIcon(); + } + } + displaySubredditIcon(); + + if(isPosting) { + mPostingSnackbar.show(); + } + + if(flair != null) { + flairTextView.setText(flair.getText()); + flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + } + if(isSpoiler) { + spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + } + if(isNSFW) { + nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); + } + } else { + getCurrentAccount(); + + isPosting = false; + + if(getIntent().hasExtra(EXTRA_SUBREDDIT_NAME)) { + loadSubredditIconSuccessful = false; + subredditName = getIntent().getStringExtra(EXTRA_SUBREDDIT_NAME); + subredditSelected = true; + subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); + subredditNameTextView.setText(subredditName); + loadSubredditIcon(); + } else { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(iconGifImageView); + } + + imageUri = getIntent().getData(); + if(imageUri != null) { + loadImage(); + } + } + + iconGifImageView.setOnClickListener(view -> { + Intent intent = new Intent(this, SubredditSelectionActivity.class); + startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); + }); + + subredditNameTextView.setOnClickListener(view -> { + Intent intent = new Intent(this, SubredditSelectionActivity.class); + startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); + }); + + rulesButton.setOnClickListener(view -> { + if(subredditName == null) { + Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); + } else { + Intent intent = new Intent(this, RulesActivity.class); + if(subredditIsUser) { + intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, "u_" + subredditName); + } else { + intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, subredditName); + } + startActivity(intent); + } + }); + + flairTextView.setOnClickListener(view -> { + if(flair == null) { + flairSelectionBottomSheetFragment = new FlairBottomSheetFragment(); + Bundle bundle = new Bundle(); + bundle.putString(FlairBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + bundle.putString(FlairBottomSheetFragment.EXTRA_SUBREDDIT_NAME, subredditName); + flairSelectionBottomSheetFragment.setArguments(bundle); + flairSelectionBottomSheetFragment.show(getSupportFragmentManager(), flairSelectionBottomSheetFragment.getTag()); + } else { + flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + flairTextView.setText(getString(R.string.flair)); + flair = null; + } + }); + + spoilerTextView.setOnClickListener(view -> { + if(!isSpoiler) { + spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + isSpoiler = true; + } else { + spoilerTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + isSpoiler = false; + } + }); + + nsfwTextView.setOnClickListener(view -> { + if(!isNSFW) { + nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); + isNSFW = true; + } else { + nsfwTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + isNSFW = false; + } + }); + + captureFab.setOnClickListener(view -> { + Intent pictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + if(pictureIntent.resolveActivity(getPackageManager()) != null) { + try { + imageUri = FileProvider.getUriForFile(this, "ml.docilealligator.infinityforreddit.provider", + File.createTempFile("temp_img", ".jpg", getExternalFilesDir(Environment.DIRECTORY_PICTURES))); + pictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); + startActivityForResult(pictureIntent, CAPTURE_IMAGE_REQUEST_CODE); + } catch (IOException ex) { + Snackbar.make(coordinatorLayout, R.string.error_creating_temp_file, Snackbar.LENGTH_SHORT).show(); + } + } else { + Snackbar.make(coordinatorLayout, R.string.no_camera_available, Snackbar.LENGTH_SHORT).show(); + } + }); + + selectFromLibraryFab.setOnClickListener(view -> { + Intent intent = new Intent(); + intent.setType("image/*"); + intent.setAction(Intent.ACTION_GET_CONTENT); + startActivityForResult(Intent.createChooser(intent,getResources().getString(R.string.select_from_gallery)), PICK_IMAGE_REQUEST_CODE); + }); + + selectAgainTextView.setOnClickListener(view -> { + imageUri = null; + selectAgainTextView.setVisibility(View.GONE); + mGlide.clear(imageView); + imageView.setVisibility(View.GONE); + constraintLayout.setVisibility(View.VISIBLE); + }); + } + + private void getCurrentAccount() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + }).execute(); + } + + private void loadImage() { + constraintLayout.setVisibility(View.GONE); + imageView.setVisibility(View.VISIBLE); + selectAgainTextView.setVisibility(View.VISIBLE); + mGlide.load(imageUri).into(imageView); + } + + private void displaySubredditIcon() { + if(iconUrl != null && !iconUrl.equals("")) { + mGlide.load(iconUrl) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(iconGifImageView); + } else { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(iconGifImageView); + } + } + + private void loadSubredditIcon() { + new LoadSubredditIconAsyncTask(mRedditDataRoomDatabase, subredditName, mRetrofit, iconImageUrl -> { + iconUrl = iconImageUrl; + displaySubredditIcon(); + loadSubredditIconSuccessful = true; + }).execute(); + } + + private void promptAlertDialog(int titleResId, int messageResId) { + new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme) + .setTitle(titleResId) + .setMessage(messageResId) + .setPositiveButton(R.string.yes, (dialogInterface, i) + -> finish()) + .setNegativeButton(R.string.no, null) + .show(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.post_image_activity, menu); + mMemu = menu; + if(isPosting) { + mMemu.findItem(R.id.action_send_post_image_activity).setEnabled(false); + mMemu.findItem(R.id.action_send_post_image_activity).getIcon().setAlpha(130); + } + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + if(isPosting) { + promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); + return true; + } else { + if(!titleEditText.getText().toString().equals("") || imageUri != null) { + promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); + return true; + } + } + finish(); + return true; + case R.id.action_send_post_image_activity: + if(!subredditSelected) { + Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); + return true; + } + + if(titleEditText.getText() == null || titleEditText.getText().toString().equals("")) { + Snackbar.make(coordinatorLayout, R.string.title_required, Snackbar.LENGTH_SHORT).show(); + return true; + } + + if(imageUri == null) { + Snackbar.make(coordinatorLayout, R.string.select_an_image, Snackbar.LENGTH_SHORT).show(); + return true; + } + + isPosting = true; + + item.setEnabled(false); + item.getIcon().setAlpha(130); + + mPostingSnackbar.show(); + + String subredditName; + if(subredditIsUser) { + subredditName = "u_" + subredditNameTextView.getText().toString(); + } else { + subredditName = subredditNameTextView.getText().toString(); + } + + Intent intent = new Intent(this, SubmitPostService.class); + intent.setData(imageUri); + intent.putExtra(SubmitPostService.EXTRA_ACCESS_TOKEN, mAccessToken); + intent.putExtra(SubmitPostService.EXTRA_SUBREDDIT_NAME, subredditName); + intent.putExtra(SubmitPostService.EXTRA_TITLE, titleEditText.getText().toString()); + intent.putExtra(SubmitPostService.EXTRA_FLAIR, flair); + intent.putExtra(SubmitPostService.EXTRA_IS_SPOILER, isSpoiler); + intent.putExtra(SubmitPostService.EXTRA_IS_NSFW, isNSFW); + intent.putExtra(SubmitPostService.EXTRA_POST_TYPE, SubmitPostService.EXTRA_POST_TYPE_IMAGE); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(intent); + } else { + startService(intent); + } + + return true; + } + + return false; + } + + @Override + public void onBackPressed() { + if(isPosting) { + promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); + } else { + if(!titleEditText.getText().toString().equals("") || imageUri != null) { + promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); + } else { + finish(); + } + } + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(SUBREDDIT_NAME_STATE, subredditName); + outState.putString(SUBREDDIT_ICON_STATE, iconUrl); + outState.putBoolean(SUBREDDIT_SELECTED_STATE, subredditSelected); + outState.putBoolean(SUBREDDIT_IS_USER_STATE, subredditIsUser); + if(imageUri != null) { + outState.putString(IMAGE_URI_STATE, imageUri.toString()); + } + outState.putBoolean(LOAD_SUBREDDIT_ICON_STATE, loadSubredditIconSuccessful); + outState.putBoolean(IS_POSTING_STATE, isPosting); + outState.putParcelable(FLAIR_STATE, flair); + outState.putBoolean(IS_SPOILER_STATE, isSpoiler); + outState.putBoolean(IS_NSFW_STATE, isNSFW); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putString(ACCOUNT_NAME_STATE, mAccountName); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if(requestCode == SUBREDDIT_SELECTION_REQUEST_CODE) { + if(resultCode == RESULT_OK) { + subredditName = data.getExtras().getString(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_NAME); + iconUrl = data.getExtras().getString(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_ICON_URL); + subredditSelected = true; + subredditIsUser = data.getExtras().getBoolean(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_IS_USER); + + subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); + subredditNameTextView.setText(subredditName); + displaySubredditIcon(); + + flairTextView.setVisibility(View.VISIBLE); + flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + flairTextView.setText(getString(R.string.flair)); + flair = null; + } + } else if(requestCode == PICK_IMAGE_REQUEST_CODE) { + if(resultCode == RESULT_OK) { + if(data == null) { + Snackbar.make(coordinatorLayout, R.string.error_getting_image, Snackbar.LENGTH_SHORT).show(); + return; + } + + imageUri = data.getData(); + loadImage(); + } + } else if(requestCode == CAPTURE_IMAGE_REQUEST_CODE) { + if(resultCode == RESULT_OK) { + loadImage(); + } + } + } + + @Override + protected void onDestroy() { + EventBus.getDefault().unregister(this); + super.onDestroy(); + } + + @Override + public void flairSelected(Flair flair) { + this.flair = flair; + flairTextView.setText(flair.getText()); + flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } + + @Subscribe + public void onSubmitImagePostEvent(SubmitImagePostEvent submitImagePostEvent) { + isPosting = false; + mPostingSnackbar.dismiss(); + if(submitImagePostEvent.postSuccess) { + Intent intent = new Intent(PostImageActivity.this, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mAccountName); + startActivity(intent); + finish(); + } else { + mMemu.findItem(R.id.action_send_post_image_activity).setEnabled(true); + mMemu.findItem(R.id.action_send_post_image_activity).getIcon().setAlpha(255); + if (submitImagePostEvent.errorMessage == null || submitImagePostEvent.errorMessage.equals("")) { + Snackbar.make(coordinatorLayout, R.string.post_failed, Snackbar.LENGTH_SHORT).show(); + } else { + Snackbar.make(coordinatorLayout, submitImagePostEvent.errorMessage.substring(0, 1).toUpperCase() + + submitImagePostEvent.errorMessage.substring(1), Snackbar.LENGTH_SHORT).show(); + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostLinkActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostLinkActivity.java new file mode 100644 index 00000000..fabb3b8c --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostLinkActivity.java @@ -0,0 +1,510 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.content.ContextCompat; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.request.RequestOptions; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; +import com.google.android.material.snackbar.Snackbar; +import com.libRG.CustomTextView; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.AsyncTask.LoadSubredditIconAsyncTask; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.Event.SubmitTextOrLinkPostEvent; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.Flair; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.Fragment.FlairBottomSheetFragment; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.RedditUtils; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.SubmitPostService; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import pl.droidsonroids.gif.GifImageView; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class PostLinkActivity extends AppCompatActivity implements FlairBottomSheetFragment.FlairSelectionCallback { + + static final String EXTRA_SUBREDDIT_NAME = "ESN"; + static final String EXTRA_LINK = "EL"; + + private static final String SUBREDDIT_NAME_STATE = "SNS"; + private static final String SUBREDDIT_ICON_STATE = "SIS"; + private static final String SUBREDDIT_SELECTED_STATE = "SSS"; + private static final String SUBREDDIT_IS_USER_STATE = "SIUS"; + private static final String LOAD_SUBREDDIT_ICON_STATE = "LSIS"; + private static final String IS_POSTING_STATE = "IPS"; + private static final String FLAIR_STATE = "FS"; + private static final String IS_SPOILER_STATE = "ISS"; + private static final String IS_NSFW_STATE = "INS"; + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + + private static final int SUBREDDIT_SELECTION_REQUEST_CODE = 0; + + @BindView(R.id.coordinator_layout_post_link_activity) CoordinatorLayout coordinatorLayout; + @BindView(R.id.toolbar_post_link_activity) Toolbar toolbar; + @BindView(R.id.subreddit_icon_gif_image_view_post_link_activity) GifImageView iconGifImageView; + @BindView(R.id.subreddit_name_text_view_post_link_activity) TextView subredditNameTextView; + @BindView(R.id.rules_button_post_link_activity) Button rulesButton; + @BindView(R.id.flair_custom_text_view_post_link_activity) CustomTextView flairTextView; + @BindView(R.id.spoiler_custom_text_view_post_link_activity) CustomTextView spoilerTextView; + @BindView(R.id.nsfw_custom_text_view_post_link_activity) CustomTextView nsfwTextView; + @BindView(R.id.post_title_edit_text_post_link_activity) EditText titleEditText; + @BindView(R.id.post_link_edit_text_post_link_activity) EditText contentEditText; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String iconUrl; + private String subredditName; + private boolean subredditSelected = false; + private boolean subredditIsUser; + private boolean loadSubredditIconSuccessful = true; + private boolean isPosting; + + private Flair flair; + private boolean isSpoiler = false; + private boolean isNSFW = false; + + private Menu mMemu; + private RequestManager mGlide; + private FlairBottomSheetFragment flairSelectionBottomSheetFragment; + private Snackbar mPostingSnackbar; + + @Inject + @Named("no_oauth") + Retrofit mRetrofit; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_post_link); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Window window = getWindow(); + if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + mGlide = Glide.with(this); + + mPostingSnackbar = Snackbar.make(coordinatorLayout, R.string.posting, Snackbar.LENGTH_INDEFINITE); + + if(savedInstanceState != null) { + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccount(); + } + + subredditName = savedInstanceState.getString(SUBREDDIT_NAME_STATE); + iconUrl = savedInstanceState.getString(SUBREDDIT_ICON_STATE); + subredditSelected = savedInstanceState.getBoolean(SUBREDDIT_SELECTED_STATE); + subredditIsUser = savedInstanceState.getBoolean(SUBREDDIT_IS_USER_STATE); + loadSubredditIconSuccessful = savedInstanceState.getBoolean(LOAD_SUBREDDIT_ICON_STATE); + isPosting = savedInstanceState.getBoolean(IS_POSTING_STATE); + flair = savedInstanceState.getParcelable(FLAIR_STATE); + isSpoiler = savedInstanceState.getBoolean(IS_SPOILER_STATE); + isNSFW = savedInstanceState.getBoolean(IS_NSFW_STATE); + + if(subredditName != null) { + subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); + subredditNameTextView.setText(subredditName); + flairTextView.setVisibility(View.VISIBLE); + if(!loadSubredditIconSuccessful) { + loadSubredditIcon(); + } + } + displaySubredditIcon(); + + if(isPosting) { + mPostingSnackbar.show(); + } + + if(flair != null) { + flairTextView.setText(flair.getText()); + flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + } + if(isSpoiler) { + spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + } + if(isNSFW) { + nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); + } + } else { + getCurrentAccount(); + + isPosting = false; + + if(getIntent().hasExtra(EXTRA_SUBREDDIT_NAME)) { + loadSubredditIconSuccessful = false; + subredditName = getIntent().getStringExtra(EXTRA_SUBREDDIT_NAME); + subredditSelected = true; + subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); + subredditNameTextView.setText(subredditName); + flairTextView.setVisibility(View.VISIBLE); + loadSubredditIcon(); + } else { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(iconGifImageView); + } + + String link = getIntent().getStringExtra(EXTRA_LINK); + if(link != null) { + contentEditText.setText(link); + } + } + + iconGifImageView.setOnClickListener(view -> { + Intent intent = new Intent(this, SubredditSelectionActivity.class); + startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); + }); + + subredditNameTextView.setOnClickListener(view -> { + Intent intent = new Intent(this, SubredditSelectionActivity.class); + startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); + }); + + rulesButton.setOnClickListener(view -> { + if(subredditName == null) { + Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); + } else { + Intent intent = new Intent(this, RulesActivity.class); + if(subredditIsUser) { + intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, "u_" + subredditName); + } else { + intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, subredditName); + } + startActivity(intent); + } + }); + + flairTextView.setOnClickListener(view -> { + if(flair == null) { + flairSelectionBottomSheetFragment = new FlairBottomSheetFragment(); + Bundle bundle = new Bundle(); + bundle.putString(FlairBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + bundle.putString(FlairBottomSheetFragment.EXTRA_SUBREDDIT_NAME, subredditName); + flairSelectionBottomSheetFragment.setArguments(bundle); + flairSelectionBottomSheetFragment.show(getSupportFragmentManager(), flairSelectionBottomSheetFragment.getTag()); + } else { + flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + flairTextView.setText(getString(R.string.flair)); + flair = null; + } + }); + + spoilerTextView.setOnClickListener(view -> { + if(!isSpoiler) { + spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + isSpoiler = true; + } else { + spoilerTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + isSpoiler = false; + } + }); + + nsfwTextView.setOnClickListener(view -> { + if(!isNSFW) { + nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); + isNSFW = true; + } else { + nsfwTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + isNSFW = false; + } + }); + } + + private void getCurrentAccount() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + } + }).execute(); + } + + private void displaySubredditIcon() { + if(iconUrl != null && !iconUrl.equals("")) { + mGlide.load(iconUrl) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(iconGifImageView); + } else { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(iconGifImageView); + } + } + + private void loadSubredditIcon() { + new LoadSubredditIconAsyncTask(mRedditDataRoomDatabase, subredditName, mRetrofit, iconImageUrl -> { + iconUrl = iconImageUrl; + displaySubredditIcon(); + loadSubredditIconSuccessful = true; + }).execute(); + } + + private void promptAlertDialog(int titleResId, int messageResId) { + new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme) + .setTitle(titleResId) + .setMessage(messageResId) + .setPositiveButton(R.string.yes, (dialogInterface, i) -> finish()) + .setNegativeButton(R.string.no, null) + .show(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.post_link_activity, menu); + mMemu = menu; + if(isPosting) { + mMemu.findItem(R.id.action_send_post_link_activity).setEnabled(false); + mMemu.findItem(R.id.action_send_post_link_activity).getIcon().setAlpha(130); + } + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + if(isPosting) { + promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); + return true; + } else { + if(!titleEditText.getText().toString().equals("") || !contentEditText.getText().toString().equals("")) { + promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); + return true; + } + } + finish(); + return true; + case R.id.action_send_post_link_activity: + if(!subredditSelected) { + Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); + return true; + } + + if(titleEditText.getText() == null || titleEditText.getText().toString().equals("")) { + Snackbar.make(coordinatorLayout, R.string.title_required, Snackbar.LENGTH_SHORT).show(); + return true; + } + + if(contentEditText.getText() == null || contentEditText.getText().toString().equals("")) { + Snackbar.make(coordinatorLayout, R.string.link_required, Snackbar.LENGTH_SHORT).show(); + return true; + } + + isPosting = true; + + item.setEnabled(false); + item.getIcon().setAlpha(130); + + mPostingSnackbar.show(); + + String subredditName; + if(subredditIsUser) { + subredditName = "u_" + subredditNameTextView.getText().toString(); + } else { + subredditName = subredditNameTextView.getText().toString(); + } + + Intent intent = new Intent(this, SubmitPostService.class); + intent.putExtra(SubmitPostService.EXTRA_ACCESS_TOKEN, mAccessToken); + intent.putExtra(SubmitPostService.EXTRA_SUBREDDIT_NAME, subredditName); + intent.putExtra(SubmitPostService.EXTRA_TITLE, titleEditText.getText().toString()); + intent.putExtra(SubmitPostService.EXTRA_CONTENT, contentEditText.getText().toString()); + intent.putExtra(SubmitPostService.EXTRA_KIND, RedditUtils.KIND_LINK); + intent.putExtra(SubmitPostService.EXTRA_FLAIR, flair); + intent.putExtra(SubmitPostService.EXTRA_IS_SPOILER, isSpoiler); + intent.putExtra(SubmitPostService.EXTRA_IS_NSFW, isNSFW); + intent.putExtra(SubmitPostService.EXTRA_POST_TYPE, SubmitPostService.EXTRA_POST_TEXT_OR_LINK); + startService(intent); + + return true; + } + + return false; + } + + @Override + public void onBackPressed() { + if(isPosting) { + promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); + } else { + if(!titleEditText.getText().toString().equals("") || !contentEditText.getText().toString().equals("")) { + promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); + } else { + finish(); + } + } + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(SUBREDDIT_NAME_STATE, subredditName); + outState.putString(SUBREDDIT_ICON_STATE, iconUrl); + outState.putBoolean(SUBREDDIT_SELECTED_STATE, subredditSelected); + outState.putBoolean(SUBREDDIT_IS_USER_STATE, subredditIsUser); + outState.putBoolean(LOAD_SUBREDDIT_ICON_STATE, loadSubredditIconSuccessful); + outState.putBoolean(IS_POSTING_STATE, isPosting); + outState.putParcelable(FLAIR_STATE, flair); + outState.putBoolean(IS_SPOILER_STATE, isSpoiler); + outState.putBoolean(IS_NSFW_STATE, isNSFW); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if(requestCode == SUBREDDIT_SELECTION_REQUEST_CODE) { + if(resultCode == RESULT_OK) { + subredditName = data.getExtras().getString(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_NAME); + iconUrl = data.getExtras().getString(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_ICON_URL); + subredditSelected = true; + subredditIsUser = data.getExtras().getBoolean(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_IS_USER); + + subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); + subredditNameTextView.setText(subredditName); + displaySubredditIcon(); + + flairTextView.setVisibility(View.VISIBLE); + flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + flairTextView.setText(getString(R.string.flair)); + flair = null; + } + } + } + + @Override + protected void onDestroy() { + EventBus.getDefault().unregister(this); + super.onDestroy(); + } + + @Override + public void flairSelected(Flair flair) { + this.flair = flair; + flairTextView.setText(flair.getText()); + flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } + + @Subscribe + public void onSubmitLinkPostEvent(SubmitTextOrLinkPostEvent submitTextOrLinkPostEvent) { + isPosting = false; + mPostingSnackbar.dismiss(); + if(submitTextOrLinkPostEvent.postSuccess) { + Intent intent = new Intent(PostLinkActivity.this, ViewPostDetailActivity.class); + intent.putExtra(ViewPostDetailActivity.EXTRA_POST_DATA, submitTextOrLinkPostEvent.post); + startActivity(intent); + finish(); + } else { + mMemu.findItem(R.id.action_send_post_link_activity).setEnabled(true); + mMemu.findItem(R.id.action_send_post_link_activity).getIcon().setAlpha(255); + if(submitTextOrLinkPostEvent.errorMessage == null) { + Snackbar.make(coordinatorLayout, R.string.post_failed, Snackbar.LENGTH_SHORT).show(); + } else { + Snackbar.make(coordinatorLayout, submitTextOrLinkPostEvent.errorMessage.substring(0, 1).toUpperCase() + + submitTextOrLinkPostEvent.errorMessage.substring(1), Snackbar.LENGTH_SHORT).show(); + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostTextActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostTextActivity.java new file mode 100644 index 00000000..4fdf63ab --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostTextActivity.java @@ -0,0 +1,510 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.content.ContextCompat; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.request.RequestOptions; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; +import com.google.android.material.snackbar.Snackbar; +import com.libRG.CustomTextView; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.AsyncTask.LoadSubredditIconAsyncTask; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.Event.SubmitTextOrLinkPostEvent; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.Flair; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.Fragment.FlairBottomSheetFragment; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.RedditUtils; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.SubmitPostService; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import pl.droidsonroids.gif.GifImageView; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class PostTextActivity extends AppCompatActivity implements FlairBottomSheetFragment.FlairSelectionCallback { + + static final String EXTRA_SUBREDDIT_NAME = "ESN"; + static final String EXTRA_CONTENT = "EC"; + + private static final String SUBREDDIT_NAME_STATE = "SNS"; + private static final String SUBREDDIT_ICON_STATE = "SIS"; + private static final String SUBREDDIT_SELECTED_STATE = "SSS"; + private static final String SUBREDDIT_IS_USER_STATE = "SIUS"; + private static final String LOAD_SUBREDDIT_ICON_STATE = "LSIS"; + private static final String IS_POSTING_STATE = "IPS"; + private static final String FLAIR_STATE = "FS"; + private static final String IS_SPOILER_STATE = "ISS"; + private static final String IS_NSFW_STATE = "INS"; + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + + private static final int SUBREDDIT_SELECTION_REQUEST_CODE = 0; + + @BindView(R.id.coordinator_layout_post_text_activity) CoordinatorLayout coordinatorLayout; + @BindView(R.id.toolbar_post_text_activity) Toolbar toolbar; + @BindView(R.id.subreddit_icon_gif_image_view_search_activity) GifImageView iconGifImageView; + @BindView(R.id.subreddit_name_text_view_search_activity) TextView subredditNameTextView; + @BindView(R.id.rules_button_post_text_activity) Button rulesButton; + @BindView(R.id.flair_custom_text_view_post_text_activity) CustomTextView flairTextView; + @BindView(R.id.spoiler_custom_text_view_post_text_activity) CustomTextView spoilerTextView; + @BindView(R.id.nsfw_custom_text_view_post_text_activity) CustomTextView nsfwTextView; + @BindView(R.id.post_title_edit_text_post_text_activity) EditText titleEditText; + @BindView(R.id.post_text_content_edit_text_post_text_activity) EditText contentEditText; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String iconUrl; + private String subredditName; + private boolean subredditSelected = false; + private boolean subredditIsUser; + private boolean loadSubredditIconSuccessful = true; + private boolean isPosting; + + private Flair flair; + private boolean isSpoiler = false; + private boolean isNSFW = false; + + private Menu mMemu; + private RequestManager mGlide; + private FlairBottomSheetFragment flairSelectionBottomSheetFragment; + private Snackbar mPostingSnackbar; + + @Inject + @Named("no_oauth") + Retrofit mRetrofit; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_post_text); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Window window = getWindow(); + if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + mGlide = Glide.with(this); + + mPostingSnackbar = Snackbar.make(coordinatorLayout, R.string.posting, Snackbar.LENGTH_INDEFINITE); + + if(savedInstanceState != null) { + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccount(); + } + + subredditName = savedInstanceState.getString(SUBREDDIT_NAME_STATE); + iconUrl = savedInstanceState.getString(SUBREDDIT_ICON_STATE); + subredditSelected = savedInstanceState.getBoolean(SUBREDDIT_SELECTED_STATE); + subredditIsUser = savedInstanceState.getBoolean(SUBREDDIT_IS_USER_STATE); + loadSubredditIconSuccessful = savedInstanceState.getBoolean(LOAD_SUBREDDIT_ICON_STATE); + isPosting = savedInstanceState.getBoolean(IS_POSTING_STATE); + flair = savedInstanceState.getParcelable(FLAIR_STATE); + isSpoiler = savedInstanceState.getBoolean(IS_SPOILER_STATE); + isNSFW = savedInstanceState.getBoolean(IS_NSFW_STATE); + + if(subredditName != null) { + subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); + subredditNameTextView.setText(subredditName); + flairTextView.setVisibility(View.VISIBLE); + if(!loadSubredditIconSuccessful) { + loadSubredditIcon(); + } + } + displaySubredditIcon(); + + if(isPosting) { + mPostingSnackbar.show(); + } + + if(flair != null) { + flairTextView.setText(flair.getText()); + flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + } + if(isSpoiler) { + spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + } + if(isNSFW) { + nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); + } + } else { + getCurrentAccount(); + + isPosting = false; + + if(getIntent().hasExtra(EXTRA_SUBREDDIT_NAME)) { + loadSubredditIconSuccessful = false; + subredditName = getIntent().getStringExtra(EXTRA_SUBREDDIT_NAME); + subredditSelected = true; + subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); + subredditNameTextView.setText(subredditName); + flairTextView.setVisibility(View.VISIBLE); + loadSubredditIcon(); + } else { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(iconGifImageView); + } + + String text = getIntent().getStringExtra(EXTRA_CONTENT); + if(text != null) { + contentEditText.setText(text); + } + } + + iconGifImageView.setOnClickListener(view -> { + Intent intent = new Intent(this, SubredditSelectionActivity.class); + startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); + }); + + subredditNameTextView.setOnClickListener(view -> { + Intent intent = new Intent(this, SubredditSelectionActivity.class); + startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); + }); + + rulesButton.setOnClickListener(view -> { + if(subredditName == null) { + Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); + } else { + Intent intent = new Intent(this, RulesActivity.class); + if(subredditIsUser) { + intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, "u_" + subredditName); + } else { + intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, subredditName); + } + startActivity(intent); + } + }); + + flairTextView.setOnClickListener(view -> { + if(flair == null) { + flairSelectionBottomSheetFragment = new FlairBottomSheetFragment(); + Bundle bundle = new Bundle(); + bundle.putString(FlairBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + if(subredditIsUser) { + bundle.putString(FlairBottomSheetFragment.EXTRA_SUBREDDIT_NAME, "u_" + subredditName); + } else { + bundle.putString(FlairBottomSheetFragment.EXTRA_SUBREDDIT_NAME, subredditName); + } + flairSelectionBottomSheetFragment.setArguments(bundle); + flairSelectionBottomSheetFragment.show(getSupportFragmentManager(), flairSelectionBottomSheetFragment.getTag()); + } else { + flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + flairTextView.setText(getString(R.string.flair)); + flair = null; + } + }); + + spoilerTextView.setOnClickListener(view -> { + if(!isSpoiler) { + spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + isSpoiler = true; + } else { + spoilerTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + isSpoiler = false; + } + }); + + nsfwTextView.setOnClickListener(view -> { + if(!isNSFW) { + nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); + isNSFW = true; + } else { + nsfwTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + isNSFW = false; + } + }); + } + + private void getCurrentAccount() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + } + }).execute(); + } + + private void displaySubredditIcon() { + if(iconUrl != null && !iconUrl.equals("")) { + mGlide.load(iconUrl) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(iconGifImageView); + } else { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(iconGifImageView); + } + } + + private void loadSubredditIcon() { + new LoadSubredditIconAsyncTask(mRedditDataRoomDatabase, subredditName, mRetrofit, iconImageUrl -> { + iconUrl = iconImageUrl; + displaySubredditIcon(); + loadSubredditIconSuccessful = true; + }).execute(); + } + + private void promptAlertDialog(int titleResId, int messageResId) { + new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme) + .setTitle(titleResId) + .setMessage(messageResId) + .setPositiveButton(R.string.yes, (dialogInterface, i) + -> finish()) + .setNegativeButton(R.string.no, null) + .show(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.post_text_activity, menu); + mMemu = menu; + if(isPosting) { + mMemu.findItem(R.id.action_send_post_text_activity).setEnabled(false); + mMemu.findItem(R.id.action_send_post_text_activity).getIcon().setAlpha(130); + } + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + if(isPosting) { + promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); + return true; + } else { + if(!titleEditText.getText().toString().equals("") || !contentEditText.getText().toString().equals("")) { + promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); + return true; + } + } + finish(); + return true; + case R.id.action_send_post_text_activity: + if(!subredditSelected) { + Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); + return true; + } + + if(titleEditText.getText() == null || titleEditText.getText().toString().equals("")) { + Snackbar.make(coordinatorLayout, R.string.title_required, Snackbar.LENGTH_SHORT).show(); + return true; + } + + isPosting = true; + + item.setEnabled(false); + item.getIcon().setAlpha(130); + + mPostingSnackbar.show(); + + String subredditName; + if(subredditIsUser) { + subredditName = "u_" + subredditNameTextView.getText().toString(); + } else { + subredditName = subredditNameTextView.getText().toString(); + } + + Intent intent = new Intent(this, SubmitPostService.class); + intent.putExtra(SubmitPostService.EXTRA_ACCESS_TOKEN, mAccessToken); + intent.putExtra(SubmitPostService.EXTRA_SUBREDDIT_NAME, subredditName); + intent.putExtra(SubmitPostService.EXTRA_TITLE, titleEditText.getText().toString()); + intent.putExtra(SubmitPostService.EXTRA_CONTENT, contentEditText.getText().toString()); + intent.putExtra(SubmitPostService.EXTRA_KIND, RedditUtils.KIND_SELF); + intent.putExtra(SubmitPostService.EXTRA_FLAIR, flair); + intent.putExtra(SubmitPostService.EXTRA_IS_SPOILER, isSpoiler); + intent.putExtra(SubmitPostService.EXTRA_IS_NSFW, isNSFW); + intent.putExtra(SubmitPostService.EXTRA_POST_TYPE, SubmitPostService.EXTRA_POST_TEXT_OR_LINK); + startService(intent); + + return true; + } + + return false; + } + + @Override + public void onBackPressed() { + if(isPosting) { + promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); + } else { + if(!titleEditText.getText().toString().equals("") || !contentEditText.getText().toString().equals("")) { + promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); + } else { + finish(); + } + } + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(SUBREDDIT_NAME_STATE, subredditName); + outState.putString(SUBREDDIT_ICON_STATE, iconUrl); + outState.putBoolean(SUBREDDIT_SELECTED_STATE, subredditSelected); + outState.putBoolean(SUBREDDIT_IS_USER_STATE, subredditIsUser); + outState.putBoolean(LOAD_SUBREDDIT_ICON_STATE, loadSubredditIconSuccessful); + outState.putBoolean(IS_POSTING_STATE, isPosting); + outState.putParcelable(FLAIR_STATE, flair); + outState.putBoolean(IS_SPOILER_STATE, isSpoiler); + outState.putBoolean(IS_NSFW_STATE, isNSFW); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if(requestCode == SUBREDDIT_SELECTION_REQUEST_CODE) { + if(resultCode == RESULT_OK) { + subredditName = data.getExtras().getString(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_NAME); + iconUrl = data.getExtras().getString(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_ICON_URL); + subredditSelected = true; + subredditIsUser = data.getExtras().getBoolean(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_IS_USER); + + subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); + subredditNameTextView.setText(subredditName); + displaySubredditIcon(); + + flairTextView.setVisibility(View.VISIBLE); + flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + flairTextView.setText(getString(R.string.flair)); + flair = null; + } + } + } + + @Override + protected void onDestroy() { + EventBus.getDefault().unregister(this); + super.onDestroy(); + } + + @Override + public void flairSelected(Flair flair) { + this.flair = flair; + flairTextView.setText(flair.getText()); + flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } + + @Subscribe + public void onSubmitTextPostEvent(SubmitTextOrLinkPostEvent submitTextOrLinkPostEvent) { + isPosting = false; + mPostingSnackbar.dismiss(); + if(submitTextOrLinkPostEvent.postSuccess) { + Intent intent = new Intent(PostTextActivity.this, ViewPostDetailActivity.class); + intent.putExtra(ViewPostDetailActivity.EXTRA_POST_DATA, submitTextOrLinkPostEvent.post); + startActivity(intent); + finish(); + } else { + mMemu.findItem(R.id.action_send_post_text_activity).setEnabled(true); + mMemu.findItem(R.id.action_send_post_text_activity).getIcon().setAlpha(255); + if(submitTextOrLinkPostEvent.errorMessage == null) { + Snackbar.make(coordinatorLayout, R.string.post_failed, Snackbar.LENGTH_SHORT).show(); + } else { + Snackbar.make(coordinatorLayout, submitTextOrLinkPostEvent.errorMessage.substring(0, 1).toUpperCase() + + submitTextOrLinkPostEvent.errorMessage.substring(1), Snackbar.LENGTH_SHORT).show(); + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostVideoActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostVideoActivity.java new file mode 100644 index 00000000..8deb269a --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/PostVideoActivity.java @@ -0,0 +1,634 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.provider.MediaStore; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.content.ContextCompat; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.request.RequestOptions; +import com.google.android.exoplayer2.ExoPlayerFactory; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.source.ExtractorMediaSource; +import com.google.android.exoplayer2.ui.PlayerView; +import com.google.android.exoplayer2.upstream.DataSource; +import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; +import com.google.android.exoplayer2.util.Util; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.google.android.material.snackbar.Snackbar; +import com.libRG.CustomTextView; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.Flair; +import ml.docilealligator.infinityforreddit.Fragment.FlairBottomSheetFragment; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.AsyncTask.LoadSubredditIconAsyncTask; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.SubmitPostService; +import ml.docilealligator.infinityforreddit.Event.SubmitVideoPostEvent; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import pl.droidsonroids.gif.GifImageView; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class PostVideoActivity extends AppCompatActivity implements FlairBottomSheetFragment.FlairSelectionCallback { + + static final String EXTRA_SUBREDDIT_NAME = "ESN"; + + private static final String SUBREDDIT_NAME_STATE = "SNS"; + private static final String SUBREDDIT_ICON_STATE = "SIS"; + private static final String SUBREDDIT_SELECTED_STATE = "SSS"; + private static final String SUBREDDIT_IS_USER_STATE = "SIUS"; + private static final String VIDEO_URI_STATE = "IUS"; + private static final String LOAD_SUBREDDIT_ICON_STATE = "LSIS"; + private static final String IS_POSTING_STATE = "IPS"; + private static final String FLAIR_STATE = "FS"; + private static final String IS_SPOILER_STATE = "ISS"; + private static final String IS_NSFW_STATE = "INS"; + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + private static final String ACCOUNT_NAME_STATE = "ANS"; + + private static final int SUBREDDIT_SELECTION_REQUEST_CODE = 0; + private static final int PICK_VIDEO_REQUEST_CODE = 1; + private static final int CAPTURE_VIDEO_REQUEST_CODE = 2; + + @BindView(R.id.coordinator_layout_post_video_activity) CoordinatorLayout coordinatorLayout; + @BindView(R.id.toolbar_post_video_activity) Toolbar toolbar; + @BindView(R.id.subreddit_icon_gif_image_view_post_video_activity) GifImageView iconGifImageView; + @BindView(R.id.subreddit_name_text_view_post_video_activity) TextView subredditNameTextView; + @BindView(R.id.rules_button_post_video_activity) Button rulesButton; + @BindView(R.id.flair_custom_text_view_post_video_activity) CustomTextView flairTextView; + @BindView(R.id.spoiler_custom_text_view_post_video_activity) CustomTextView spoilerTextView; + @BindView(R.id.nsfw_custom_text_view_post_video_activity) CustomTextView nsfwTextView; + @BindView(R.id.post_title_edit_text_post_video_activity) EditText titleEditText; + @BindView(R.id.select_video_constraint_layout_post_video_activity) ConstraintLayout constraintLayout; + @BindView(R.id.capture_fab_post_video_activity) FloatingActionButton captureFab; + @BindView(R.id.select_from_library_fab_post_video_activity) FloatingActionButton selectFromLibraryFab; + @BindView(R.id.select_again_text_view_post_video_activity) TextView selectAgainTextView; + @BindView(R.id.player_view_post_video_activity) PlayerView videoPlayerView; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String mAccountName; + private String iconUrl; + private String subredditName; + private boolean subredditSelected = false; + private boolean subredditIsUser; + private Uri videoUri; + private boolean loadSubredditIconSuccessful = true; + private boolean isPosting; + private boolean wasPlaying; + + private Flair flair; + private boolean isSpoiler = false; + private boolean isNSFW = false; + + private Menu mMemu; + private RequestManager mGlide; + private FlairBottomSheetFragment mFlairSelectionBottomSheetFragment; + private Snackbar mPostingSnackbar; + + private DataSource.Factory dataSourceFactory; + private SimpleExoPlayer player; + + @Inject + @Named("no_oauth") + Retrofit mRetrofit; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + @Named("upload_media") + Retrofit mUploadMediaRetrofit; + + @Inject + @Named("upload_video") + Retrofit mUploadVideoRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_post_video); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Window window = getWindow(); + if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + mGlide = Glide.with(this); + + player = ExoPlayerFactory.newSimpleInstance(this); + videoPlayerView.setPlayer(player); + dataSourceFactory = new DefaultDataSourceFactory(this, + Util.getUserAgent(this, "Infinity")); + player.setRepeatMode(Player.REPEAT_MODE_ALL); + + mPostingSnackbar = Snackbar.make(coordinatorLayout, R.string.posting, Snackbar.LENGTH_INDEFINITE); + + if(savedInstanceState != null) { + subredditName = savedInstanceState.getString(SUBREDDIT_NAME_STATE); + iconUrl = savedInstanceState.getString(SUBREDDIT_ICON_STATE); + subredditSelected = savedInstanceState.getBoolean(SUBREDDIT_SELECTED_STATE); + subredditIsUser = savedInstanceState.getBoolean(SUBREDDIT_IS_USER_STATE); + loadSubredditIconSuccessful = savedInstanceState.getBoolean(LOAD_SUBREDDIT_ICON_STATE); + isPosting = savedInstanceState.getBoolean(IS_POSTING_STATE); + flair = savedInstanceState.getParcelable(FLAIR_STATE); + isSpoiler = savedInstanceState.getBoolean(IS_SPOILER_STATE); + isNSFW = savedInstanceState.getBoolean(IS_NSFW_STATE); + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); + + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccount(); + } + + if(savedInstanceState.getString(VIDEO_URI_STATE) != null) { + videoUri = Uri.parse(savedInstanceState.getString(VIDEO_URI_STATE)); + loadVideo(); + } + + if(subredditName != null) { + subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); + subredditNameTextView.setText(subredditName); + flairTextView.setVisibility(View.VISIBLE); + if(!loadSubredditIconSuccessful) { + loadSubredditIcon(); + } + } + displaySubredditIcon(); + + if(isPosting) { + mPostingSnackbar.show(); + } + + if(flair != null) { + flairTextView.setText(flair.getText()); + flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + } + if(isSpoiler) { + spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + } + if(isNSFW) { + nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); + } + } else { + getCurrentAccount(); + + isPosting = false; + + if(getIntent().hasExtra(EXTRA_SUBREDDIT_NAME)) { + loadSubredditIconSuccessful = false; + subredditName = getIntent().getStringExtra(EXTRA_SUBREDDIT_NAME); + subredditSelected = true; + subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); + subredditNameTextView.setText(subredditName); + loadSubredditIcon(); + } else { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(iconGifImageView); + } + + videoUri = getIntent().getData(); + if(videoUri != null) { + loadVideo(); + } + } + + iconGifImageView.setOnClickListener(view -> { + Intent intent = new Intent(this, SubredditSelectionActivity.class); + startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); + }); + + subredditNameTextView.setOnClickListener(view -> { + Intent intent = new Intent(this, SubredditSelectionActivity.class); + startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); + }); + + rulesButton.setOnClickListener(view -> { + if(subredditName == null) { + Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); + } else { + Intent intent = new Intent(this, RulesActivity.class); + if(subredditIsUser) { + intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, "u_" + subredditName); + } else { + intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, subredditName); + } + startActivity(intent); + } + }); + + flairTextView.setOnClickListener(view -> { + if(flair == null) { + mFlairSelectionBottomSheetFragment = new FlairBottomSheetFragment(); + Bundle bundle = new Bundle(); + bundle.putString(FlairBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + bundle.putString(FlairBottomSheetFragment.EXTRA_SUBREDDIT_NAME, subredditName); + mFlairSelectionBottomSheetFragment.setArguments(bundle); + mFlairSelectionBottomSheetFragment.show(getSupportFragmentManager(), mFlairSelectionBottomSheetFragment.getTag()); + } else { + flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + flairTextView.setText(getString(R.string.flair)); + flair = null; + } + }); + + spoilerTextView.setOnClickListener(view -> { + if(!isSpoiler) { + spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + isSpoiler = true; + } else { + spoilerTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + isSpoiler = false; + } + }); + + nsfwTextView.setOnClickListener(view -> { + if(!isNSFW) { + nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); + isNSFW = true; + } else { + nsfwTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + isNSFW = false; + } + }); + + captureFab.setOnClickListener(view -> { + Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); + if (takeVideoIntent.resolveActivity(getPackageManager()) != null) { + startActivityForResult(takeVideoIntent, CAPTURE_VIDEO_REQUEST_CODE); + } + }); + + selectFromLibraryFab.setOnClickListener(view -> { + Intent intent = new Intent(); + intent.setType("video/*"); + intent.setAction(Intent.ACTION_GET_CONTENT); + startActivityForResult(Intent.createChooser(intent,getResources().getString(R.string.select_from_gallery)), PICK_VIDEO_REQUEST_CODE); + }); + + selectAgainTextView.setOnClickListener(view -> { + wasPlaying = false; + player.setPlayWhenReady(false); + videoUri = null; + videoPlayerView.setVisibility(View.GONE); + selectAgainTextView.setVisibility(View.GONE); + constraintLayout.setVisibility(View.VISIBLE); + }); + } + + private void getCurrentAccount() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + }).execute(); + } + + private void loadVideo() { + constraintLayout.setVisibility(View.GONE); + selectAgainTextView.setVisibility(View.VISIBLE); + videoPlayerView.setVisibility(View.VISIBLE); + player.prepare(new ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(videoUri)); + player.setPlayWhenReady(true); + wasPlaying = true; + } + + private void displaySubredditIcon() { + if(iconUrl != null && !iconUrl.equals("")) { + mGlide.load(iconUrl) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(iconGifImageView); + } else { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(iconGifImageView); + } + } + + private void loadSubredditIcon() { + new LoadSubredditIconAsyncTask(mRedditDataRoomDatabase, subredditName, mRetrofit, iconImageUrl -> { + iconUrl = iconImageUrl; + displaySubredditIcon(); + loadSubredditIconSuccessful = true; + }).execute(); + } + + private void promptAlertDialog(int titleResId, int messageResId) { + new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme) + .setTitle(titleResId) + .setMessage(messageResId) + .setPositiveButton(R.string.yes, (dialogInterface, i) -> finish()) + .setNegativeButton(R.string.no, null) + .show(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.post_video_activity, menu); + mMemu = menu; + if(isPosting) { + mMemu.findItem(R.id.action_send_post_video_activity).setEnabled(false); + mMemu.findItem(R.id.action_send_post_video_activity).getIcon().setAlpha(130); + } + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + if(isPosting) { + promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); + return true; + } else { + if(!titleEditText.getText().toString().equals("") || videoUri != null) { + promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); + return true; + } + } + finish(); + return true; + case R.id.action_send_post_video_activity: + if(!subredditSelected) { + Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); + return true; + } + + if(titleEditText.getText() == null || titleEditText.getText().toString().equals("")) { + Snackbar.make(coordinatorLayout, R.string.title_required, Snackbar.LENGTH_SHORT).show(); + return true; + } + + if(videoUri == null) { + Snackbar.make(coordinatorLayout, R.string.select_an_image, Snackbar.LENGTH_SHORT).show(); + return true; + } + + isPosting = true; + + item.setEnabled(false); + item.getIcon().setAlpha(130); + + mPostingSnackbar.show(); + + String subredditName; + if(subredditIsUser) { + subredditName = "u_" + subredditNameTextView.getText().toString(); + } else { + subredditName = subredditNameTextView.getText().toString(); + } + + Intent intent = new Intent(this, SubmitPostService.class); + intent.setData(videoUri); + intent.putExtra(SubmitPostService.EXTRA_ACCESS_TOKEN, mAccessToken); + intent.putExtra(SubmitPostService.EXTRA_SUBREDDIT_NAME, subredditName); + intent.putExtra(SubmitPostService.EXTRA_TITLE, titleEditText.getText().toString()); + intent.putExtra(SubmitPostService.EXTRA_FLAIR, flair); + intent.putExtra(SubmitPostService.EXTRA_IS_SPOILER, isSpoiler); + intent.putExtra(SubmitPostService.EXTRA_IS_NSFW, isNSFW); + intent.putExtra(SubmitPostService.EXTRA_POST_TYPE, SubmitPostService.EXTRA_POST_TYPE_VIDEO); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(intent); + } else { + startService(intent); + } + + return true; + } + + return false; + } + + @Override + public void onBackPressed() { + if(isPosting) { + promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); + } else { + if(!titleEditText.getText().toString().equals("") || videoUri != null) { + promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); + } else { + finish(); + } + } + } + + @Override + protected void onStart() { + super.onStart(); + if(wasPlaying) { + player.setPlayWhenReady(true); + } + } + + @Override + protected void onStop() { + super.onStop(); + player.setPlayWhenReady(false); + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(SUBREDDIT_NAME_STATE, subredditName); + outState.putString(SUBREDDIT_ICON_STATE, iconUrl); + outState.putBoolean(SUBREDDIT_SELECTED_STATE, subredditSelected); + outState.putBoolean(SUBREDDIT_IS_USER_STATE, subredditIsUser); + if(videoUri != null) { + outState.putString(VIDEO_URI_STATE, videoUri.toString()); + } + outState.putBoolean(LOAD_SUBREDDIT_ICON_STATE, loadSubredditIconSuccessful); + outState.putBoolean(IS_POSTING_STATE, isPosting); + outState.putParcelable(FLAIR_STATE, flair); + outState.putBoolean(IS_SPOILER_STATE, isSpoiler); + outState.putBoolean(IS_NSFW_STATE, isNSFW); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putString(ACCOUNT_NAME_STATE, mAccountName); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if(requestCode == SUBREDDIT_SELECTION_REQUEST_CODE) { + if(resultCode == RESULT_OK) { + if(data != null) { + subredditName = data.getStringExtra(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_NAME); + iconUrl = data.getStringExtra(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_ICON_URL); + subredditSelected = true; + subredditIsUser = data.getBooleanExtra(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_IS_USER, false); + + subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); + subredditNameTextView.setText(subredditName); + displaySubredditIcon(); + + flairTextView.setVisibility(View.VISIBLE); + flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + flairTextView.setText(getString(R.string.flair)); + flair = null; + } + } + } else if(requestCode == PICK_VIDEO_REQUEST_CODE) { + if(resultCode == RESULT_OK) { + if(data == null) { + Snackbar.make(coordinatorLayout, R.string.error_getting_video, Snackbar.LENGTH_SHORT).show(); + return; + } + + videoUri = data.getData(); + loadVideo(); + } + } else if (requestCode == CAPTURE_VIDEO_REQUEST_CODE) { + if(resultCode == RESULT_OK) { + if(data != null && data.getData() != null) { + videoUri = data.getData(); + loadVideo(); + } else { + Snackbar.make(coordinatorLayout, R.string.error_getting_video, Snackbar.LENGTH_SHORT).show(); + } + } + } + } + + @Override + protected void onDestroy() { + EventBus.getDefault().unregister(this); + super.onDestroy(); + player.release(); + } + + @Override + public void flairSelected(Flair flair) { + this.flair = flair; + flairTextView.setText(flair.getText()); + flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } + + @Subscribe + public void onSubmitVideoPostEvent(SubmitVideoPostEvent submitVideoPostEvent) { + isPosting = false; + mPostingSnackbar.dismiss(); + mMemu.findItem(R.id.action_send_post_video_activity).setEnabled(true); + mMemu.findItem(R.id.action_send_post_video_activity).getIcon().setAlpha(255); + + if(submitVideoPostEvent.postSuccess) { + Intent intent = new Intent(this, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, + mAccountName); + startActivity(intent); + finish(); + } else if(submitVideoPostEvent.errorProcessingVideo) { + Snackbar.make(coordinatorLayout, R.string.error_processing_video, Snackbar.LENGTH_SHORT).show(); + } else { + if (submitVideoPostEvent.errorMessage == null || submitVideoPostEvent.errorMessage.equals("")) { + Snackbar.make(coordinatorLayout, R.string.post_failed, Snackbar.LENGTH_SHORT).show(); + } else { + Snackbar.make(coordinatorLayout, submitVideoPostEvent.errorMessage.substring(0, 1).toUpperCase() + + submitVideoPostEvent.errorMessage.substring(1), Snackbar.LENGTH_SHORT).show(); + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/RulesActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/RulesActivity.java new file mode 100644 index 00000000..d0d739a9 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/RulesActivity.java @@ -0,0 +1,292 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Bundle; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ProgressBar; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.appbar.AppBarLayout; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.Adapter.RulesRecyclerViewAdapter; +import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.JSONUtils; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditAPI; +import ml.docilealligator.infinityforreddit.Rule; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import ml.docilealligator.infinityforreddit.Utils; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class RulesActivity extends AppCompatActivity { + + static final String EXTRA_SUBREDDIT_NAME = "ESN"; + + @BindView(R.id.appbar_layout_rules_activity) AppBarLayout appBarLayout; + @BindView(R.id.toolbar_rules_activity) Toolbar toolbar; + @BindView(R.id.progress_bar_rules_activity) ProgressBar progressBar; + @BindView(R.id.recycler_view_rules_activity) RecyclerView recyclerView; + @BindView(R.id.error_text_view_rules_activity) TextView errorTextView; + + private String mSubredditName; + + private RulesRecyclerViewAdapter mAdapter; + + @Inject + @Named("no_oauth") + Retrofit mRetrofit; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_rules); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + Resources resources = getResources(); + + if(resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + + boolean lightNavBar = false; + if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + lightNavBar = true; + } + boolean finalLightNavBar = lightNavBar; + + View decorView = window.getDecorView(); + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, State state) { + if(state == State.COLLAPSED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } else if(state == State.EXPANDED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } + } + }); + + int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (statusBarResourceId > 0) { + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); + params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); + toolbar.setLayoutParams(params); + } + + if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { + int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); + if (navBarResourceId > 0) { + recyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); + } + } + } + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + mSubredditName = getIntent().getExtras().getString(EXTRA_SUBREDDIT_NAME); + + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + mAdapter = new RulesRecyclerViewAdapter(this); + recyclerView.setAdapter(mAdapter); + + fetchRules(); + } + + private void fetchRules() { + progressBar.setVisibility(View.VISIBLE); + errorTextView.setVisibility(View.GONE); + + RedditAPI api = mRetrofit.create(RedditAPI.class); + Call rulesCall = api.getRules(mSubredditName); + rulesCall.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if(response.isSuccessful()) { + new ParseRulesAsyncTask(response.body(), new ParseRulesAsyncTask.ParseRulesAsyncTaskListener() { + @Override + public void parseSuccessful(ArrayList rules) { + progressBar.setVisibility(View.GONE); + if(rules == null || rules.size() == 0) { + errorTextView.setVisibility(View.VISIBLE); + errorTextView.setText(R.string.no_rule); + errorTextView.setOnClickListener(view -> {}); + } + mAdapter.changeDataset(rules); + } + + @Override + public void parseFailed() { + displayError(); + } + }).execute(); + } else { + displayError(); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + displayError(); + } + }); + } + + private void displayError() { + progressBar.setVisibility(View.GONE); + errorTextView.setVisibility(View.VISIBLE); + errorTextView.setText(R.string.error_loading_rules); + errorTextView.setOnClickListener(view -> fetchRules()); + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if(item.getItemId() == android.R.id.home) { + finish(); + return true; + } + + return false; + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } + + private static class ParseRulesAsyncTask extends AsyncTask, ArrayList> { + private String response; + private ParseRulesAsyncTaskListener parseRulesAsyncTaskListener; + + interface ParseRulesAsyncTaskListener { + void parseSuccessful(ArrayList rules); + void parseFailed(); + } + + ParseRulesAsyncTask(String response, ParseRulesAsyncTaskListener parseRulesAsyncTaskListener) { + this.response = response; + this.parseRulesAsyncTaskListener = parseRulesAsyncTaskListener; + } + + @Override + protected ArrayList doInBackground(Void... voids) { + try { + JSONArray rulesArray = new JSONObject(response).getJSONArray(JSONUtils.RULES_KEY); + ArrayList rules = new ArrayList<>(); + for(int i = 0; i < rulesArray.length(); i++) { + String shortName = rulesArray.getJSONObject(i).getString(JSONUtils.SHORT_NAME_KEY); + String description = null; + if(rulesArray.getJSONObject(i).has(JSONUtils.DESCRIPTION_KEY)) { + description = Utils.addSubredditAndUserLink(rulesArray.getJSONObject(i).getString(JSONUtils.DESCRIPTION_KEY)); + } + rules.add(new Rule(shortName, description)); + } + return rules; + } catch (JSONException e) { + e.printStackTrace(); + } + return null; + } + + @Override + protected void onPostExecute(ArrayList rules) { + if(rules != null) { + parseRulesAsyncTaskListener.parseSuccessful(rules); + } else { + parseRulesAsyncTaskListener.parseFailed(); + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SearchActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SearchActivity.java new file mode 100644 index 00000000..03796d20 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SearchActivity.java @@ -0,0 +1,305 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.view.inputmethod.InputMethodManager; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.core.content.ContextCompat; + +import com.ferfalk.simplesearchview.SimpleSearchView; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import javax.inject.Inject; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.TitleFontStyle; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class SearchActivity extends AppCompatActivity { + + static final String EXTRA_QUERY = "EQ"; + static final String EXTRA_SUBREDDIT_NAME = "ESN"; + static final String EXTRA_SUBREDDIT_IS_USER = "ESIU"; + static final String EXTRA_SEARCH_ONLY_SUBREDDITS = "ESOS"; + static final String EXTRA_RETURN_SUBREDDIT_NAME = "ERSN"; + static final String EXTRA_RETURN_SUBREDDIT_ICON_URL = "ERSIURL"; + + private static final String SUBREDDIT_NAME_STATE = "SNS"; + private static final String SUBREDDIT_IS_USER_STATE = "SIUS"; + + private static final int SUBREDDIT_SELECTION_REQUEST_CODE = 0; + private static final int SUBREDDIT_SEARCH_REQUEST_CODE = 1; + + @BindView(R.id.toolbar) Toolbar toolbar; + @BindView(R.id.search_view_search_activity) SimpleSearchView simpleSearchView; + @BindView(R.id.subreddit_name_relative_layout_search_activity) RelativeLayout subredditNameRelativeLayout; + @BindView(R.id.subreddit_name_text_view_search_activity) TextView subredditNameTextView; + + private String query; + private String subredditName; + private boolean subredditIsUser; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_search); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Window window = getWindow(); + if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + + boolean searchOnlySubreddits = getIntent().getExtras().getBoolean(EXTRA_SEARCH_ONLY_SUBREDDITS); + + simpleSearchView.setOnSearchViewListener(new SimpleSearchView.SearchViewListener() { + @Override + public void onSearchViewShown() { + + } + + @Override + public void onSearchViewClosed() { + finish(); + } + + @Override + public void onSearchViewShownAnimation() { + + } + + @Override + public void onSearchViewClosedAnimation() { + + } + }); + + simpleSearchView.setOnQueryTextListener(new SimpleSearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String query) { + if(searchOnlySubreddits) { + Intent intent = new Intent(SearchActivity.this, SearchSubredditsResultActivity.class); + intent.putExtra(SearchSubredditsResultActivity.EXTRA_QUERY, query); + startActivityForResult(intent, SUBREDDIT_SEARCH_REQUEST_CODE); + } else { + Intent intent = new Intent(SearchActivity.this, SearchResultActivity.class); + intent.putExtra(SearchResultActivity.EXTRA_QUERY, query); + if(subredditName != null) { + if(subredditIsUser) { + intent.putExtra(SearchResultActivity.EXTRA_SUBREDDIT_NAME, "u_" + subredditName); + } else { + intent.putExtra(SearchResultActivity.EXTRA_SUBREDDIT_NAME, subredditName); + } + } + startActivity(intent); + finish(); + } + return true; + } + + @Override + public boolean onQueryTextChange(String newText) { + return false; + } + + @Override + public boolean onQueryTextCleared() { + return false; + } + }); + + if(savedInstanceState != null) { + subredditName = savedInstanceState.getString(SUBREDDIT_NAME_STATE); + subredditIsUser = savedInstanceState.getBoolean(SUBREDDIT_IS_USER_STATE); + + if(subredditName == null) { + subredditNameTextView.setText(R.string.all_subreddits); + } else { + subredditNameTextView.setText(subredditName); + } + } else { + query = getIntent().getStringExtra(EXTRA_QUERY); + } + + if(searchOnlySubreddits) { + subredditNameRelativeLayout.setVisibility(View.GONE); + } else { + subredditNameRelativeLayout.setOnClickListener(view -> { + Intent intent = new Intent(this, SubredditSelectionActivity.class); + intent.putExtra(SubredditSelectionActivity.EXTRA_EXTRA_CLEAR_SELECTION, true); + startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); + }); + } + + Intent intent = getIntent(); + if(intent.hasExtra(EXTRA_SUBREDDIT_NAME)) { + subredditName = intent.getExtras().getString(EXTRA_SUBREDDIT_NAME); + subredditNameTextView.setText(subredditName); + subredditIsUser = intent.getExtras().getBoolean(EXTRA_SUBREDDIT_IS_USER); + } + } + + @Override + protected void onStart() { + super.onStart(); + simpleSearchView.showSearch(false); + simpleSearchView.getSearchEditText().requestFocus(); + + if(query != null) { + simpleSearchView.getSearchEditText().setText(query); + simpleSearchView.getSearchEditText().setSelection(query.length()); + query = null; + } + + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + if(imm != null) { + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + } + } + + @Override + protected void onPause() { + super.onPause(); + InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); + if(imm != null) { + imm.hideSoftInputFromWindow(simpleSearchView.getSearchEditText().getWindowToken(), 0); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + if (simpleSearchView.onActivityResult(requestCode, resultCode, data)) { + return; + } + + if(requestCode == SUBREDDIT_SELECTION_REQUEST_CODE) { + if(resultCode == RESULT_OK) { + subredditName = data.getExtras().getString(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_NAME); + subredditIsUser = data.getExtras().getBoolean(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_IS_USER); + + if(subredditName == null) { + subredditNameTextView.setText(R.string.all_subreddits); + } else { + subredditNameTextView.setText(subredditName); + } + } + } else if(requestCode == SUBREDDIT_SEARCH_REQUEST_CODE) { + if(resultCode == RESULT_OK) { + String name = data.getExtras().getString(SearchSubredditsResultActivity.EXTRA_RETURN_SUBREDDIT_NAME); + String iconUrl = data.getExtras().getString(SearchSubredditsResultActivity.EXTRA_RETURN_SUBREDDIT_ICON_URL); + Intent returnIntent = new Intent(); + returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_NAME, name); + returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_ICON_URL, iconUrl); + setResult(Activity.RESULT_OK, returnIntent); + finish(); + } + } + + super.onActivityResult(requestCode, resultCode, data); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.search_activity, menu); + simpleSearchView.setMenuItem(menu.findItem(R.id.action_search_search_activity)); + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if(item.getItemId() == android.R.id.home) { + finish(); + return true; + } + + return false; + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(SUBREDDIT_NAME_STATE, subredditName); + outState.putBoolean(SUBREDDIT_IS_USER_STATE, subredditIsUser); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SearchResultActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SearchResultActivity.java new file mode 100644 index 00000000..5f28d994 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SearchResultActivity.java @@ -0,0 +1,412 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.tabs.TabLayout; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import javax.inject.Inject; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; +import ml.docilealligator.infinityforreddit.Event.ChangeNSFWEvent; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.FragmentCommunicator; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.Fragment.PostFragment; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.Fragment.SearchPostSortTypeBottomSheetFragment; +import ml.docilealligator.infinityforreddit.Fragment.SearchUserAndSubredditSortTypeBottomSheetFragment; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.Fragment.SubredditListingFragment; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import ml.docilealligator.infinityforreddit.Fragment.UserListingFragment; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class SearchResultActivity extends AppCompatActivity implements SearchPostSortTypeBottomSheetFragment.SearchSortTypeSelectionCallback, + SearchUserAndSubredditSortTypeBottomSheetFragment.SearchUserAndSubredditSortTypeSelectionCallback { + static final String EXTRA_QUERY = "QK"; + static final String EXTRA_SUBREDDIT_NAME = "ESN"; + + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + private static final String ACCOUNT_NAME_STATE = "ANS"; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String mAccountName; + private String mQuery; + private String mSubredditName; + + @BindView(R.id.appbar_layout_search_result_activity) AppBarLayout appBarLayout; + @BindView(R.id.toolbar_search_result_activity) Toolbar toolbar; + @BindView(R.id.tab_layout_search_result_activity) TabLayout tabLayout; + @BindView(R.id.view_pager_search_result_activity) ViewPager viewPager; + + private SectionsPagerAdapter sectionsPagerAdapter; + + private SearchPostSortTypeBottomSheetFragment searchPostSortTypeBottomSheetFragment; + private SearchUserAndSubredditSortTypeBottomSheetFragment searchUserAndSubredditSortTypeBottomSheetFragment; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_search_result); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + Resources resources = getResources(); + + if(resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + + boolean lightNavBar = false; + if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + lightNavBar = true; + } + boolean finalLightNavBar = lightNavBar; + + View decorView = window.getDecorView(); + appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, State state) { + if(state == State.COLLAPSED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } else if(state == State.EXPANDED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } + } + }); + + int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (statusBarResourceId > 0) { + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); + params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); + toolbar.setLayoutParams(params); + } + } + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + if(savedInstanceState == null) { + getCurrentAccountAndInitializeViewPager(); + } else { + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccountAndInitializeViewPager(); + } else { + initializeViewPager(); + } + } + + searchPostSortTypeBottomSheetFragment = new SearchPostSortTypeBottomSheetFragment(); + Bundle bundle = new Bundle(); + searchPostSortTypeBottomSheetFragment.setArguments(bundle); + + searchUserAndSubredditSortTypeBottomSheetFragment = new SearchUserAndSubredditSortTypeBottomSheetFragment(); + + // Get the intent, verify the action and get the query + Intent intent = getIntent(); + String query = intent.getStringExtra(EXTRA_QUERY); + + mSubredditName = intent.getStringExtra(EXTRA_SUBREDDIT_NAME); + + if(query != null) { + mQuery = query; + setTitle(query); + } + } + + private void getCurrentAccountAndInitializeViewPager() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + initializeViewPager(); + }).execute(); + } + + private void initializeViewPager() { + sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); + viewPager.setAdapter(sectionsPagerAdapter); + viewPager.setOffscreenPageLimit(2); + tabLayout.setupWithViewPager(viewPager); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.search_result_activity, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + onBackPressed(); + return true; + case R.id.action_sort_search_result_activity: + switch (viewPager.getCurrentItem()) { + case 0: { + searchPostSortTypeBottomSheetFragment.show(getSupportFragmentManager(), searchPostSortTypeBottomSheetFragment.getTag()); + break; + } + case 1: + case 2: + Bundle bundle = new Bundle(); + bundle.putInt(SearchUserAndSubredditSortTypeBottomSheetFragment.EXTRA_FRAGMENT_POSITION, viewPager.getCurrentItem()); + searchUserAndSubredditSortTypeBottomSheetFragment.setArguments(bundle); + searchUserAndSubredditSortTypeBottomSheetFragment.show(getSupportFragmentManager(), searchUserAndSubredditSortTypeBottomSheetFragment.getTag()); + break; + } + return true; + case R.id.action_search_search_result_activity: + Intent intent = new Intent(this, SearchActivity.class); + intent.putExtra(SearchActivity.EXTRA_SEARCH_ONLY_SUBREDDITS, false); + intent.putExtra(SearchActivity.EXTRA_QUERY, mQuery); + finish(); + startActivity(intent); + return true; + case R.id.action_refresh_search_result_activity: + sectionsPagerAdapter.refresh(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putString(ACCOUNT_NAME_STATE, mAccountName); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void searchSortTypeSelected(String sortType) { + sectionsPagerAdapter.changeSortType(sortType, 0); + } + + @Override + public void searchUserAndSubredditSortTypeSelected(String sortType, int fragmentPosition) { + sectionsPagerAdapter.changeSortType(sortType, fragmentPosition); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } + + @Subscribe + public void onChangeNSFWEvent(ChangeNSFWEvent changeNSFWEvent) { + sectionsPagerAdapter.changeNSFW(changeNSFWEvent.nsfw); + } + + private class SectionsPagerAdapter extends FragmentPagerAdapter { + + private PostFragment postFragment; + private SubredditListingFragment subredditListingFragment; + private UserListingFragment userListingFragment; + + public SectionsPagerAdapter(FragmentManager fm) { + super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); + } + + @NonNull + @Override + public Fragment getItem(int position) { + switch (position) { + case 0: { + PostFragment mFragment = new PostFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_SEARCH); + bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_RELEVANCE); + bundle.putString(PostFragment.EXTRA_NAME, mSubredditName); + bundle.putString(PostFragment.EXTRA_QUERY, mQuery); + bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); + bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + mFragment.setArguments(bundle); + return mFragment; + } + case 1: { + SubredditListingFragment mFragment = new SubredditListingFragment(); + Bundle bundle = new Bundle(); + bundle.putString(SubredditListingFragment.EXTRA_QUERY, mQuery); + bundle.putBoolean(SubredditListingFragment.EXTRA_IS_POSTING, false); + bundle.putString(SubredditListingFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + bundle.putString(SubredditListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); + mFragment.setArguments(bundle); + return mFragment; + } + default: { + UserListingFragment mFragment = new UserListingFragment(); + Bundle bundle = new Bundle(); + bundle.putString(UserListingFragment.EXTRA_QUERY, mQuery); + bundle.putString(UserListingFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + bundle.putString(UserListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); + mFragment.setArguments(bundle); + return mFragment; + } + } + } + + @Override + public int getCount() { + return 3; + } + + @Override + public CharSequence getPageTitle(int position) { + switch (position) { + case 0: + return "Posts"; + case 1: + return "Subreddits"; + case 2: + return "Users"; + } + return null; + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + Fragment fragment = (Fragment) super.instantiateItem(container, position); + switch (position) { + case 0: + postFragment = (PostFragment) fragment; + break; + case 1: + subredditListingFragment = (SubredditListingFragment) fragment; + break; + case 2: + userListingFragment = (UserListingFragment) fragment; + break; + } + return fragment; + } + + void changeSortType(String sortType, int fragmentPosition) { + switch (fragmentPosition) { + case 0: + postFragment.changeSortType(sortType); + break; + case 1: + subredditListingFragment.changeSortType(sortType); + break; + case 2: + userListingFragment.changeSortType(sortType); + } + } + + public void refresh() { + switch (viewPager.getCurrentItem()) { + case 0: + ((FragmentCommunicator) postFragment).refresh(); + break; + case 1: + ((FragmentCommunicator) subredditListingFragment).refresh(); + break; + case 2: + ((FragmentCommunicator) userListingFragment).refresh(); + break; + } + } + + public void changeNSFW(boolean nsfw) { + if(postFragment != null) { + postFragment.changeNSFW(nsfw); + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SearchSubredditsResultActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SearchSubredditsResultActivity.java new file mode 100644 index 00000000..cc4bee19 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SearchSubredditsResultActivity.java @@ -0,0 +1,229 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.app.Activity; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.Fragment; + +import com.google.android.material.appbar.AppBarLayout; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import javax.inject.Inject; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.Fragment.SubredditListingFragment; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.TitleFontStyle; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class SearchSubredditsResultActivity extends AppCompatActivity { + + static final String EXTRA_QUERY = "EQ"; + static final String EXTRA_RETURN_SUBREDDIT_NAME = "ERSN"; + static final String EXTRA_RETURN_SUBREDDIT_ICON_URL = "ERSIURL"; + + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + private static final String ACCOUNT_NAME_STATE = "ANS"; + private static final String FRAGMENT_OUT_STATE = "FOS"; + + @BindView(R.id.appbar_layout_search_subreddits_result_activity) AppBarLayout appBarLayout; + @BindView(R.id.toolbar_search_subreddits_result_activity) Toolbar toolbar; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String mAccountName; + + Fragment mFragment; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_search_subreddits_result); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + Resources resources = getResources(); + + if(resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + + boolean lightNavBar = false; + if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + lightNavBar = true; + } + boolean finalLightNavBar = lightNavBar; + + View decorView = window.getDecorView(); + appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, State state) { + if(state == State.COLLAPSED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } else if(state == State.EXPANDED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } + } + }); + + int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (statusBarResourceId > 0) { + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); + params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); + toolbar.setLayoutParams(params); + } + } + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + String query = getIntent().getExtras().getString(EXTRA_QUERY); + + if(savedInstanceState == null) { + getCurrentAccountAndInitializeFragment(query); + } else { + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccountAndInitializeFragment(query); + } else { + mFragment = getSupportFragmentManager().getFragment(savedInstanceState, FRAGMENT_OUT_STATE); + getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_search_subreddits_result_activity, mFragment).commit(); + } + } + } + + private void getCurrentAccountAndInitializeFragment(String query) { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + + mFragment = new SubredditListingFragment(); + Bundle bundle = new Bundle(); + bundle.putString(SubredditListingFragment.EXTRA_QUERY, query); + bundle.putBoolean(SubredditListingFragment.EXTRA_IS_POSTING, true); + bundle.putString(SubredditListingFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + bundle.putString(SubredditListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); + mFragment.setArguments(bundle); + getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_search_subreddits_result_activity, mFragment).commit(); + }).execute(); + } + + public void getSelectedSubreddit(String name, String iconUrl) { + Intent returnIntent = new Intent(); + returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_NAME, name); + returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_ICON_URL, iconUrl); + setResult(Activity.RESULT_OK, returnIntent); + finish(); + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if(item.getItemId() == android.R.id.home) { + finish(); + return true; + } + return false; + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + if (mFragment != null) { + getSupportFragmentManager().putFragment(outState, FRAGMENT_OUT_STATE, mFragment); + } + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putString(ACCOUNT_NAME_STATE, mAccountName); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SettingsActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SettingsActivity.java new file mode 100644 index 00000000..98849878 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SettingsActivity.java @@ -0,0 +1,154 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.preference.Preference; +import androidx.preference.PreferenceFragmentCompat; + +import javax.inject.Inject; + +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.Settings.AboutPreferenceFragment; +import ml.docilealligator.infinityforreddit.Settings.MainPreferenceFragment; +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.TitleFontStyle; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class SettingsActivity extends AppCompatActivity implements + PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { + + private static final String TITLE_STATE = "TS"; + + @BindView(R.id.toolbar_settings_activity) Toolbar toolbar; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.settings_activity); + + ButterKnife.bind(this); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Window window = getWindow(); + if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + + if (savedInstanceState == null) { + getSupportFragmentManager() + .beginTransaction() + .replace(R.id.frame_layout_settings_activity, new MainPreferenceFragment()) + .commit(); + } else { + setTitle(savedInstanceState.getCharSequence(TITLE_STATE)); + } + getSupportFragmentManager().addOnBackStackChangedListener(() -> { + if (getSupportFragmentManager().getBackStackEntryCount() == 0) { + setTitle(R.string.settings_activity_label); + } else if (getSupportFragmentManager().findFragmentById(R.id.frame_layout_settings_activity) instanceof AboutPreferenceFragment) { + setTitle(R.string.settings_about_master_title); + } + }); + + + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if(item.getItemId() == android.R.id.home) { + onBackPressed(); + return true; + } + return false; + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putCharSequence(TITLE_STATE, getTitle()); + } + + @Override + public boolean onSupportNavigateUp() { + if (getSupportFragmentManager().popBackStackImmediate()) { + return true; + } + return super.onSupportNavigateUp(); + } + + @Override + public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) { + // Instantiate the new Fragment + final Bundle args = pref.getExtras(); + final Fragment fragment = getSupportFragmentManager().getFragmentFactory().instantiate( + getClassLoader(), + pref.getFragment()); + fragment.setArguments(args); + fragment.setTargetFragment(caller, 0); + + getSupportFragmentManager().beginTransaction() + .replace(R.id.frame_layout_settings_activity, fragment) + .addToBackStack(null) + .commit(); + setTitle(pref.getTitle()); + return true; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ShareDataResolverActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ShareDataResolverActivity.java new file mode 100644 index 00000000..3468ab66 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ShareDataResolverActivity.java @@ -0,0 +1,83 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.util.Patterns; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; + +import ml.docilealligator.infinityforreddit.Activity.PostImageActivity; +import ml.docilealligator.infinityforreddit.Activity.PostLinkActivity; +import ml.docilealligator.infinityforreddit.Activity.PostTextActivity; +import ml.docilealligator.infinityforreddit.Activity.PostVideoActivity; +import ml.docilealligator.infinityforreddit.R; + +public class ShareDataResolverActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Intent receivedIntent = getIntent(); + String action = receivedIntent.getAction(); + String type = receivedIntent.getType(); + + if(Intent.ACTION_SEND.equals(action) && type != null) { + if("text/plain".equals(type)) { + String text = receivedIntent.getStringExtra(Intent.EXTRA_TEXT); + if(text != null) { + if(Patterns.WEB_URL.matcher(text).matches()) { + //It's a link + Intent intent = new Intent(this, PostLinkActivity.class); + intent.putExtra(PostLinkActivity.EXTRA_LINK, text); + startActivity(intent); + } else { + Intent intent = new Intent(this, PostTextActivity.class); + intent.putExtra(PostTextActivity.EXTRA_CONTENT, text); + startActivity(intent); + } + } else { + Toast.makeText(this, R.string.no_data_received, Toast.LENGTH_SHORT).show(); + } + } else if(type.equals("image/gif")) { + Uri videoUri = receivedIntent.getParcelableExtra(Intent.EXTRA_STREAM); + if(videoUri != null) { + Intent intent = new Intent(this, PostVideoActivity.class); + intent.setData(videoUri); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + startActivity(intent); + } else { + Toast.makeText(this, R.string.no_video_path_received, Toast.LENGTH_SHORT).show(); + } + } else if(type.startsWith("image/")) { + Uri imageUri = receivedIntent.getParcelableExtra(Intent.EXTRA_STREAM); + if(imageUri != null) { + Intent intent = new Intent(this, PostImageActivity.class); + intent.setData(imageUri); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + startActivity(intent); + } else { + Toast.makeText(this, R.string.no_image_path_received, Toast.LENGTH_SHORT).show(); + } + } else if(type.startsWith("video/")) { + Uri videoUri = receivedIntent.getParcelableExtra(Intent.EXTRA_STREAM); + if(videoUri != null) { + Intent intent = new Intent(this, PostVideoActivity.class); + intent.setData(videoUri); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + startActivity(intent); + } else { + Toast.makeText(this, R.string.no_video_path_received, Toast.LENGTH_SHORT).show(); + } + } else { + Toast.makeText(this, R.string.cannot_handle_intent, Toast.LENGTH_SHORT).show(); + } + } else { + Toast.makeText(this, R.string.cannot_handle_intent, Toast.LENGTH_SHORT).show(); + } + + finish(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SubredditSelectionActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SubredditSelectionActivity.java new file mode 100644 index 00000000..1b060e91 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SubredditSelectionActivity.java @@ -0,0 +1,323 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.app.Activity; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.Fragment; + +import com.google.android.material.appbar.AppBarLayout; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import java.util.ArrayList; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.AsyncTask.InsertSubscribedThingsAsyncTask; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.FetchSubscribedThing; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.Fragment.SubscribedSubredditsListingFragment; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditData; +import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditData; +import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserData; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class SubredditSelectionActivity extends AppCompatActivity { + + static final String EXTRA_EXTRA_CLEAR_SELECTION = "EECS"; + static final String EXTRA_RETURN_SUBREDDIT_NAME = "ERSN"; + static final String EXTRA_RETURN_SUBREDDIT_ICON_URL = "ERSIURL"; + static final String EXTRA_RETURN_SUBREDDIT_IS_USER = "ERSIU"; + + private static final int SUBREDDIT_SEARCH_REQUEST_CODE = 0; + private static final String INSERT_SUBSCRIBED_SUBREDDIT_STATE = "ISSS"; + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + private static final String ACCOUNT_NAME_STATE = "ANS"; + private static final String ACCOUNT_PROFILE_IMAGE_URL = "APIU"; + private static final String FRAGMENT_OUT_STATE = "FOS"; + + @BindView(R.id.appbar_layout_subreddit_selection_activity) AppBarLayout appBarLayout; + @BindView(R.id.toolbar_subreddit_selection_activity) Toolbar toolbar; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String mAccountName; + private String mAccountProfileImageUrl; + private boolean mInsertSuccess = false; + + private Fragment mFragment; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_subreddit_selection); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + Resources resources = getResources(); + + if(resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + + boolean lightNavBar = false; + if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + lightNavBar = true; + } + boolean finalLightNavBar = lightNavBar; + + View decorView = window.getDecorView(); + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, State state) { + if(state == State.COLLAPSED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } else if(state == State.EXPANDED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } + } + }); + + int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (statusBarResourceId > 0) { + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); + params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); + toolbar.setLayoutParams(params); + } + } + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + if(savedInstanceState == null) { + getCurrentAccountAndBindView(); + } else { + mInsertSuccess = savedInstanceState.getBoolean(INSERT_SUBSCRIBED_SUBREDDIT_STATE); + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); + mAccountProfileImageUrl = savedInstanceState.getString(ACCOUNT_PROFILE_IMAGE_URL); + + if(!mNullAccessToken && mAccountName == null) { + getCurrentAccountAndBindView(); + } else { + mFragment = getSupportFragmentManager().getFragment(savedInstanceState, FRAGMENT_OUT_STATE); + getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_subreddit_selection_activity, mFragment).commit(); + } + } + } + + private void getCurrentAccountAndBindView() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + mAccountProfileImageUrl = account.getProfileImageUrl(); + } + bindView(); + }).execute(); + } + + private void bindView() { + loadSubscriptions(); + + mFragment = new SubscribedSubredditsListingFragment(); + Bundle bundle = new Bundle(); + bundle.putString(SubscribedSubredditsListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); + bundle.putString(SubscribedSubredditsListingFragment.EXTRA_ACCOUNT_PROFILE_IMAGE_URL, mAccountProfileImageUrl); + bundle.putBoolean(SubscribedSubredditsListingFragment.EXTRA_IS_SUBREDDIT_SELECTION, true); + if(getIntent().hasExtra(EXTRA_EXTRA_CLEAR_SELECTION)) { + bundle.putBoolean(SubscribedSubredditsListingFragment.EXTRA_EXTRA_CLEAR_SELECTION, + getIntent().getExtras().getBoolean(EXTRA_EXTRA_CLEAR_SELECTION)); + } + mFragment.setArguments(bundle); + getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_subreddit_selection_activity, mFragment).commit(); + } + + private void loadSubscriptions() { + if (!mInsertSuccess) { + FetchSubscribedThing.fetchSubscribedThing(mOauthRetrofit, mAccessToken, mAccountName, null, + new ArrayList<>(), new ArrayList<>(), + new ArrayList<>(), + new FetchSubscribedThing.FetchSubscribedThingListener() { + @Override + public void onFetchSubscribedThingSuccess(ArrayList subscribedSubredditData, + ArrayList subscribedUserData, + ArrayList subredditData) { + new InsertSubscribedThingsAsyncTask( + mRedditDataRoomDatabase, + mAccountName, + subscribedSubredditData, + subscribedUserData, + subredditData, + () -> mInsertSuccess = true).execute(); + } + + @Override + public void onFetchSubscribedThingFail() { + mInsertSuccess = false; + } + }); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.subreddit_selection_activity, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + case R.id.action_search_subreddit_selection_activity: + Intent intent = new Intent(this, SearchActivity.class); + intent.putExtra(SearchActivity.EXTRA_SEARCH_ONLY_SUBREDDITS, true); + startActivityForResult(intent, SUBREDDIT_SEARCH_REQUEST_CODE); + return true; + } + + return false; + } + + public void getSelectedSubreddit(String name, String iconUrl, boolean subredditIsUser) { + Intent returnIntent = new Intent(); + returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_NAME, name); + returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_ICON_URL, iconUrl); + returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_IS_USER, subredditIsUser); + setResult(Activity.RESULT_OK, returnIntent); + finish(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + if(requestCode == SUBREDDIT_SEARCH_REQUEST_CODE) { + if(resultCode == RESULT_OK) { + String name = data.getStringExtra(SearchActivity.EXTRA_RETURN_SUBREDDIT_NAME); + String iconUrl = data.getStringExtra(SearchActivity.EXTRA_RETURN_SUBREDDIT_ICON_URL); + Intent returnIntent = new Intent(); + returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_NAME, name); + returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_ICON_URL, iconUrl); + returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_IS_USER, false); + setResult(Activity.RESULT_OK, returnIntent); + finish(); + } + } + super.onActivityResult(requestCode, resultCode, data); + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + if (mFragment != null) { + getSupportFragmentManager().putFragment(outState, FRAGMENT_OUT_STATE, mFragment); + } + outState.putBoolean(INSERT_SUBSCRIBED_SUBREDDIT_STATE, mInsertSuccess); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putString(ACCOUNT_NAME_STATE, mAccountName); + outState.putString(ACCOUNT_PROFILE_IMAGE_URL, mAccountProfileImageUrl); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SubscribedThingListingActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SubscribedThingListingActivity.java new file mode 100644 index 00000000..73e22730 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SubscribedThingListingActivity.java @@ -0,0 +1,317 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.tabs.TabLayout; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import java.util.ArrayList; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.AsyncTask.InsertSubscribedThingsAsyncTask; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.FetchSubscribedThing; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.Fragment.FollowedUsersListingFragment; +import ml.docilealligator.infinityforreddit.Fragment.SubscribedSubredditsListingFragment; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditData; +import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditData; +import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserData; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class SubscribedThingListingActivity extends AppCompatActivity { + + private static final String INSERT_SUBSCRIBED_SUBREDDIT_STATE = "ISSS"; + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + private static final String ACCOUNT_NAME_STATE = "ANS"; + + @BindView(R.id.appbar_layout_subscribed_thing_listing_activity) AppBarLayout appBarLayout; + @BindView(R.id.toolbar_subscribed_thing_listing_activity) Toolbar toolbar; + @BindView(R.id.tab_layout_subscribed_thing_listing_activity) TabLayout tabLayout; + @BindView(R.id.view_pager_subscribed_thing_listing_activity) ViewPager viewPager; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String mAccountName; + private boolean mInsertSuccess = false; + + private SectionsPagerAdapter sectionsPagerAdapter; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_subscribed_thing_listing); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + Resources resources = getResources(); + + if(resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + + boolean lightNavBar = false; + if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + lightNavBar = true; + } + boolean finalLightNavBar = lightNavBar; + + View decorView = window.getDecorView(); + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, State state) { + if(state == State.COLLAPSED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } else if(state == State.EXPANDED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } + } + }); + + int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (statusBarResourceId > 0) { + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); + params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); + toolbar.setLayoutParams(params); + } + } + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + if(savedInstanceState != null) { + mInsertSuccess = savedInstanceState.getBoolean(INSERT_SUBSCRIBED_SUBREDDIT_STATE); + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccountAndInitializeViewPager(); + } else { + initializeViewPagerAndLoadSubscriptions(); + } + } else { + getCurrentAccountAndInitializeViewPager(); + } + } + + private void getCurrentAccountAndInitializeViewPager() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + initializeViewPagerAndLoadSubscriptions(); + }).execute(); + } + + private void initializeViewPagerAndLoadSubscriptions() { + sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); + viewPager.setAdapter(sectionsPagerAdapter); + viewPager.setOffscreenPageLimit(2); + tabLayout.setupWithViewPager(viewPager); + + loadSubscriptions(); + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if(item.getItemId() == android.R.id.home) { + finish(); + return true; + } + + return false; + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(INSERT_SUBSCRIBED_SUBREDDIT_STATE, mInsertSuccess); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putString(ACCOUNT_NAME_STATE, mAccountName); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + private void loadSubscriptions() { + if (!mInsertSuccess) { + FetchSubscribedThing.fetchSubscribedThing(mOauthRetrofit, mAccessToken, mAccountName, null, + new ArrayList<>(), new ArrayList<>(), + new ArrayList<>(), + new FetchSubscribedThing.FetchSubscribedThingListener() { + @Override + public void onFetchSubscribedThingSuccess(ArrayList subscribedSubredditData, + ArrayList subscribedUserData, + ArrayList subredditData) { + new InsertSubscribedThingsAsyncTask( + mRedditDataRoomDatabase, + mAccountName, + subscribedSubredditData, + subscribedUserData, + subredditData, + () -> mInsertSuccess = true).execute(); + } + + @Override + public void onFetchSubscribedThingFail() { + mInsertSuccess = false; + } + }); + } + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } + + private class SectionsPagerAdapter extends FragmentPagerAdapter { + + public SectionsPagerAdapter(FragmentManager fm) { + super(fm); + } + + @NonNull + @Override + public Fragment getItem(int position) { + switch (position) { + case 0: { + SubscribedSubredditsListingFragment fragment = new SubscribedSubredditsListingFragment(); + Bundle bundle = new Bundle(); + bundle.putBoolean(SubscribedSubredditsListingFragment.EXTRA_IS_SUBREDDIT_SELECTION, false); + bundle.putString(SubscribedSubredditsListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); + fragment.setArguments(bundle); + return fragment; + } + default: + { + FollowedUsersListingFragment fragment = new FollowedUsersListingFragment(); + Bundle bundle = new Bundle(); + bundle.putString(FollowedUsersListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); + fragment.setArguments(bundle); + return fragment; + } + } + } + + @Override + public int getCount() { + return 2; + } + + @Override + public CharSequence getPageTitle(int position) { + switch (position) { + case 0: + return getString(R.string.subreddits); + case 1: + return getString(R.string.users); + } + + return null; + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + return super.instantiateItem(container, position); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewImageActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewImageActivity.java new file mode 100644 index 00000000..20a9318a --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewImageActivity.java @@ -0,0 +1,468 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.Manifest; +import android.animation.Animator; +import android.animation.ArgbEvaluator; +import android.animation.ValueAnimator; +import android.app.DownloadManager; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.graphics.PorterDuff; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Environment; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import com.alexvasilkov.gestures.GestureController; +import com.alexvasilkov.gestures.State; +import com.alexvasilkov.gestures.views.GestureImageView; +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.RequestOptions; +import com.bumptech.glide.request.target.Target; +import com.github.pwittchen.swipe.library.rx2.SimpleSwipeListener; +import com.github.pwittchen.swipe.library.rx2.Swipe; + +import java.io.File; + +import javax.inject.Inject; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.TitleFontStyle; + +public class ViewImageActivity extends AppCompatActivity { + + private static final int PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 0; + + public static final String TITLE_KEY = "TK"; + public static final String IMAGE_URL_KEY = "IUK"; + public static final String FILE_NAME_KEY = "FNK"; + + @BindView(R.id.parent_relative_layout_view_image_activity) RelativeLayout mRelativeLayout; + @BindView(R.id.progress_bar_view_image_activity) ProgressBar mProgressBar; + @BindView(R.id.image_view_view_image_activity) GestureImageView mImageView; + @BindView(R.id.load_image_error_linear_layout_view_image_activity) LinearLayout mLoadErrorLinearLayout; + + private boolean isActionBarHidden = false; + private boolean isDownloading = false; + + private Menu mMenu; + private Swipe swipe; + + private String mImageUrl; + private String mImageFileName; + + private float totalLengthY = 0.0f; + private float touchY = -1.0f; + private float zoom = 1.0f; + + private boolean isSwiping = false; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_view_image); + + ButterKnife.bind(this); + + ActionBar actionBar = getSupportActionBar(); + Drawable upArrow = getResources().getDrawable(R.drawable.ic_arrow_back_white_24dp); + actionBar.setHomeAsUpIndicator(upArrow); + actionBar.setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.transparentActionBarAndExoPlayerControllerColor))); + setTitle(""); + + Intent intent = getIntent(); + mImageUrl = intent.getStringExtra(IMAGE_URL_KEY); + mImageFileName = intent.getStringExtra(FILE_NAME_KEY) + ".jpg"; + + mLoadErrorLinearLayout.setOnClickListener(view -> { + if(!isSwiping) { + mProgressBar.setVisibility(View.VISIBLE); + mLoadErrorLinearLayout.setVisibility(View.GONE); + loadImage(); + } + }); + + float pxHeight = getResources().getDisplayMetrics().heightPixels; + + int activityColorFrom = getResources().getColor(android.R.color.black); + int actionBarColorFrom = getResources().getColor(R.color.transparentActionBarAndExoPlayerControllerColor); + int actionBarElementColorFrom = getResources().getColor(android.R.color.white); + int colorTo = getResources().getColor(android.R.color.transparent); + + final ValueAnimator activityColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), activityColorFrom, colorTo); + final ValueAnimator actionBarColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), actionBarColorFrom, colorTo); + final ValueAnimator actionBarElementColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), actionBarElementColorFrom, colorTo); + + activityColorAnimation.setDuration(300); // milliseconds + actionBarColorAnimation.setDuration(300); + actionBarElementColorAnimation.setDuration(300); + + activityColorAnimation.addUpdateListener(valueAnimator -> mRelativeLayout.setBackgroundColor((int) valueAnimator.getAnimatedValue())); + + actionBarColorAnimation.addUpdateListener(valueAnimator -> actionBar.setBackgroundDrawable(new ColorDrawable((int) valueAnimator.getAnimatedValue()))); + + actionBarElementColorAnimation.addUpdateListener(valueAnimator -> { + upArrow.setColorFilter((int) valueAnimator.getAnimatedValue(), PorterDuff.Mode.SRC_IN); + if(mMenu != null) { + Drawable drawable = mMenu.getItem(0).getIcon(); + //drawable.mutate(); + drawable.setColorFilter((int) valueAnimator.getAnimatedValue(), PorterDuff.Mode.SRC_IN); + } + }); + + loadImage(); + + swipe = new Swipe(); + swipe.setListener(new SimpleSwipeListener() { + @Override + public void onSwipingUp(final MotionEvent event) { + isSwiping = true; + float nowY = event.getY(); + float offset; + if (touchY == -1.0f) { + offset = 0.0f; + } else { + offset = nowY - touchY; + } + totalLengthY += offset; + touchY = nowY; + mImageView.animate() + .y(totalLengthY) + .setDuration(0) + .start(); + mLoadErrorLinearLayout.animate() + .y(totalLengthY) + .setDuration(0) + .start(); + } + + @Override + public boolean onSwipedUp(final MotionEvent event) { + if (totalLengthY < -pxHeight / 8) { + mImageView.animate() + .y(-pxHeight) + .setDuration(300) + .setListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animator) { + activityColorAnimation.start(); + actionBarColorAnimation.start(); + actionBarElementColorAnimation.start(); + } + + @Override + public void onAnimationEnd(Animator animator) { + finish(); + } + + @Override + public void onAnimationCancel(Animator animator) { + } + + @Override + public void onAnimationRepeat(Animator animator) { + } + }) + .start(); + mLoadErrorLinearLayout.animate() + .y(-pxHeight) + .setDuration(300) + .start(); + } else { + isSwiping = false; + mImageView.animate() + .y(0) + .setDuration(300) + .start(); + mLoadErrorLinearLayout.animate() + .y(0) + .setDuration(300) + .start(); + } + + totalLengthY = 0.0f; + touchY = -1.0f; + return false; + } + + @Override + public void onSwipingDown(final MotionEvent event) { + isSwiping = true; + float nowY = event.getY(); + float offset; + if (touchY == -1.0f) { + offset = 0.0f; + } else { + offset = nowY - touchY; + } + totalLengthY += offset; + touchY = nowY; + mImageView.animate() + .y(totalLengthY) + .setDuration(0) + .start(); + mLoadErrorLinearLayout.animate() + .y(totalLengthY) + .setDuration(0) + .start(); + } + + @Override + public boolean onSwipedDown(final MotionEvent event) { + if (totalLengthY > pxHeight / 8) { + mImageView.animate() + .y(pxHeight) + .setDuration(300) + .setListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animator) { + activityColorAnimation.start(); + actionBarColorAnimation.start(); + actionBarElementColorAnimation.start(); + } + + @Override + public void onAnimationEnd(Animator animator) { + finish(); + } + + @Override + public void onAnimationCancel(Animator animator) { + } + + @Override + public void onAnimationRepeat(Animator animator) { + } + }) + .start(); + mLoadErrorLinearLayout.animate() + .y(pxHeight) + .setDuration(300) + .start(); + } else { + isSwiping = false; + mImageView.animate() + .y(0) + .setDuration(300) + .start(); + mLoadErrorLinearLayout.animate() + .y(0) + .setDuration(300) + .start(); + } + + totalLengthY = 0.0f; + touchY = -1.0f; + + return false; + } + }); + + mImageView.getController().addOnStateChangeListener(new GestureController.OnStateChangeListener() { + @Override + public void onStateChanged(State state) { + zoom = state.getZoom(); + } + + @Override + public void onStateReset(State oldState, State newState) { + + } + }); + + mImageView.getController().getSettings().setMaxZoom(10f).setDoubleTapZoom(2f).setPanEnabled(true); + + mImageView.setOnClickListener(view -> { + if (isActionBarHidden) { + getWindow().getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); + isActionBarHidden = false; + } else { + getWindow().getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_IMMERSIVE); + isActionBarHidden = true; + } + }); + } + + private void loadImage() { + Glide.with(this).load(mImageUrl).listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + mProgressBar.setVisibility(View.GONE); + mLoadErrorLinearLayout.setVisibility(View.VISIBLE); + return false; + } + + @Override + public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + mProgressBar.setVisibility(View.GONE); + return false; + } + }).apply(new RequestOptions().fitCenter()).into(mImageView); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + mMenu = menu; + getMenuInflater().inflate(R.menu.view_image, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + case R.id.action_download_view_image: + if (isDownloading) { + return false; + } + + isDownloading = true; + + if (Build.VERSION.SDK_INT >= 23) { + if (ContextCompat.checkSelfPermission(this, + Manifest.permission.WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + + // Permission is not granted + // No explanation needed; request the permission + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE); + } else { + // Permission has already been granted + saveImage(); + } + } else { + saveImage(); + } + + return true; + } + + return false; + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if(zoom == 1.0) { + swipe.dispatchTouchEvent(ev); + } + return super.dispatchTouchEvent(ev); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if(requestCode == PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE && grantResults.length > 0) { + if(grantResults[0] == PackageManager.PERMISSION_DENIED) { + Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show(); + } else if(grantResults[0] == PackageManager.PERMISSION_GRANTED && isDownloading) { + saveImage(); + } + isDownloading = false; + } + } + + private void saveImage() { + DownloadManager.Request request = new DownloadManager.Request(Uri.parse(mImageUrl)); + request.setTitle(mImageFileName); + + request.allowScanningByMediaScanner(); + request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); + + //Android Q support + if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + request.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES, mImageFileName); + } else { + String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString(); + File directory = new File(path + "/Infinity/"); + boolean saveToInfinityFolder = true; + if(!directory.exists()) { + if(!directory.mkdir()) { + saveToInfinityFolder = false; + } + } else { + if(directory.isFile()) { + if(!(directory.delete() && directory.mkdir())) { + saveToInfinityFolder = false; + } + } + } + + if(saveToInfinityFolder) { + request.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES + "/Infinity/", mImageFileName); + } else { + request.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES, mImageFileName); + } + } + + DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); + + if(manager == null) { + Toast.makeText(this, R.string.download_failed, Toast.LENGTH_SHORT).show(); + return; + } + + manager.enqueue(request); + Toast.makeText(this, R.string.download_started, Toast.LENGTH_SHORT).show(); + } + + @Override + protected void onPause() { + super.onPause(); + overridePendingTransition(0, 0); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewMessageActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewMessageActivity.java new file mode 100644 index 00000000..e6999b7d --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewMessageActivity.java @@ -0,0 +1,333 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.appbar.CollapsingToolbarLayout; +import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.FetchMessages; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.Adapter.MessageRecyclerViewAdapter; +import ml.docilealligator.infinityforreddit.MessageViewModel; +import ml.docilealligator.infinityforreddit.NetworkState; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.AsyncTask.SwitchAccountAsyncTask; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class ViewMessageActivity extends AppCompatActivity { + + public static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; + + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + private static final String NEW_ACCOUNT_NAME_STATE = "NANS"; + + @BindView(R.id.collapsing_toolbar_layout_view_message_activity) CollapsingToolbarLayout collapsingToolbarLayout; + @BindView(R.id.appbar_layout_view_message_activity) AppBarLayout appBarLayout; + @BindView(R.id.toolbar_view_message_activity) Toolbar toolbar; + @BindView(R.id.progress_bar_view_message_activity) CircleProgressBar mProgressBar; + @BindView(R.id.recycler_view_view_message_activity) RecyclerView recyclerView; + @BindView(R.id.fetch_messages_info_linear_layout_view_message_activity) LinearLayout mFetchMessageInfoLinearLayout; + @BindView(R.id.fetch_messages_info_image_view_view_message_activity) ImageView mFetchMessageInfoImageView; + @BindView(R.id.fetch_messages_info_text_view_view_message_activity) TextView mFetchMessageInfoTextView; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String mNewAccountName; + + private MessageRecyclerViewAdapter mAdapter; + + private RequestManager mGlide; + + MessageViewModel mMessageViewModel; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_view_message); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + mGlide = Glide.with(this); + + Resources resources = getResources(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 + && (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT + || resources.getBoolean(R.bool.isTablet))) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + + boolean lightNavBar = false; + if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + lightNavBar = true; + } + boolean finalLightNavBar = lightNavBar; + + View decorView = window.getDecorView(); + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, State state) { + if (state == State.COLLAPSED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } else if (state == State.EXPANDED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } + } + }); + + int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (statusBarResourceId > 0) { + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); + params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); + toolbar.setLayoutParams(params); + } + + int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); + if (navBarResourceId > 0) { + recyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); + } + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + toolbar.setTitle(R.string.inbox); + setSupportActionBar(toolbar); + + if(savedInstanceState != null) { + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + mNewAccountName = savedInstanceState.getString(NEW_ACCOUNT_NAME_STATE); + + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccountAndFetchMessage(); + } else { + bindView(); + } + } else { + mNewAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); + getCurrentAccountAndFetchMessage(); + } + } + + private void getCurrentAccountAndFetchMessage() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(mNewAccountName != null) { + if(account == null || !account.getUsername().equals(mNewAccountName)) { + new SwitchAccountAsyncTask(mRedditDataRoomDatabase, mNewAccountName, newAccount -> { + EventBus.getDefault().post(new SwitchAccountEvent(getClass().getName())); + Toast.makeText(this, R.string.account_switched, Toast.LENGTH_SHORT).show(); + + mNewAccountName = null; + if(newAccount == null) { + mNullAccessToken = true; + } else { + mAccessToken = newAccount.getAccessToken(); + } + + bindView(); + }).execute(); + } else { + mAccessToken = account.getAccessToken(); + bindView(); + } + } else { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + } + + bindView(); + } + }).execute(); + } + + private void bindView() { + mAdapter = new MessageRecyclerViewAdapter(this, mOauthRetrofit, mAccessToken, + () -> mMessageViewModel.retryLoadingMore()); + LinearLayoutManager layoutManager = new LinearLayoutManager(this); + recyclerView.setLayoutManager(layoutManager); + recyclerView.setAdapter(mAdapter); + DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this, layoutManager.getOrientation()); + recyclerView.addItemDecoration(dividerItemDecoration); + + MessageViewModel.Factory factory = new MessageViewModel.Factory(mOauthRetrofit, + getResources().getConfiguration().locale, mAccessToken, FetchMessages.WHERE_INBOX); + mMessageViewModel = new ViewModelProvider(this, factory).get(MessageViewModel.class); + mMessageViewModel.getMessages().observe(this, messages -> mAdapter.submitList(messages)); + + mMessageViewModel.hasMessage().observe(this, hasMessage -> { + mProgressBar.setVisibility(View.GONE); + if(hasMessage) { + mFetchMessageInfoLinearLayout.setVisibility(View.GONE); + } else { + mFetchMessageInfoLinearLayout.setOnClickListener(view -> { + //Do nothing + }); + showErrorView(R.string.no_messages); + } + }); + + mMessageViewModel.getInitialLoadingState().observe(this, networkState -> { + if(networkState.getStatus().equals(NetworkState.Status.SUCCESS)) { + mProgressBar.setVisibility(View.GONE); + } else if(networkState.getStatus().equals(NetworkState.Status.FAILED)) { + mProgressBar.setVisibility(View.GONE); + mFetchMessageInfoLinearLayout.setOnClickListener(view -> { + mFetchMessageInfoLinearLayout.setVisibility(View.GONE); + mMessageViewModel.refresh(); + mAdapter.setNetworkState(null); + }); + showErrorView(R.string.load_messages_failed); + } else { + mProgressBar.setVisibility(View.VISIBLE); + } + }); + + mMessageViewModel.getPaginationNetworkState().observe(this, networkState -> { + mAdapter.setNetworkState(networkState); + }); + } + + private void showErrorView(int stringResId) { + mProgressBar.setVisibility(View.GONE); + mFetchMessageInfoLinearLayout.setVisibility(View.VISIBLE); + mFetchMessageInfoTextView.setText(stringResId); + mGlide.load(R.drawable.error_image).into(mFetchMessageInfoImageView); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.view_message_activity, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if(item.getItemId() == R.id.action_refresh_view_message_activity) { + mMessageViewModel.refresh(); + mAdapter.setNetworkState(null); + return true; + } else if(item.getItemId() == android.R.id.home) { + finish(); + return true; + } + return false; + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putString(NEW_ACCOUNT_NAME_STATE, mNewAccountName); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + if(!getClass().getName().equals(event.excludeActivityClassName)) { + finish(); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java new file mode 100644 index 00000000..f57fe4cb --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java @@ -0,0 +1,1320 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.evernote.android.state.State; +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; +import com.google.android.material.snackbar.Snackbar; +import com.livefront.bridge.Bridge; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; +import ml.docilealligator.infinityforreddit.Event.ChangeNSFWBlurEvent; +import ml.docilealligator.infinityforreddit.Event.ChangeSpoilerBlurEvent; +import ml.docilealligator.infinityforreddit.Adapter.CommentAndPostRecyclerViewAdapter; +import ml.docilealligator.infinityforreddit.CommentData; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.DeleteThing; +import ml.docilealligator.infinityforreddit.FetchComment; +import ml.docilealligator.infinityforreddit.FetchPost; +import ml.docilealligator.infinityforreddit.Flair; +import ml.docilealligator.infinityforreddit.Fragment.FlairBottomSheetFragment; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.HidePost; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.ParseComment; +import ml.docilealligator.infinityforreddit.ParsePost; +import ml.docilealligator.infinityforreddit.Post; +import ml.docilealligator.infinityforreddit.Event.PostUpdateEventToDetailActivity; +import ml.docilealligator.infinityforreddit.Event.PostUpdateEventToPostList; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.ReadMessage; +import ml.docilealligator.infinityforreddit.RedditAPI; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.RedditUtils; +import ml.docilealligator.infinityforreddit.SaveThing; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.AsyncTask.SwitchAccountAsyncTask; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; +import static ml.docilealligator.infinityforreddit.Activity.CommentActivity.EXTRA_COMMENT_DATA_KEY; +import static ml.docilealligator.infinityforreddit.Activity.CommentActivity.WRITE_COMMENT_REQUEST_CODE; + +public class ViewPostDetailActivity extends AppCompatActivity implements FlairBottomSheetFragment.FlairSelectionCallback { + + public static final String EXTRA_POST_DATA = "EPD"; + public static final String EXTRA_POST_LIST_POSITION = "EPLI"; + public static final String EXTRA_POST_ID = "EPI"; + public static final String EXTRA_SINGLE_COMMENT_ID = "ESCI"; + public static final String EXTRA_MESSAGE_FULLNAME = "ENI"; + public static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; + + private static final int EDIT_POST_REQUEST_CODE = 2; + public static final int EDIT_COMMENT_REQUEST_CODE = 3; + + private RequestManager mGlide; + private Locale mLocale; + private Menu mMenu; + + private int orientation; + private int postListPosition = -1; + private String mSingleCommentId; + private boolean mNeedBlurNsfw; + private boolean mNeedBlurSpoiler; + + @State + boolean mNullAccessToken = false; + @State + String mAccessToken; + @State + String mAccountName; + @State + Post mPost; + @State + boolean isLoadingMoreChildren = false; + @State + boolean isRefreshing = false; + @State + boolean isSingleCommentThreadMode = false; + @State + ArrayList comments; + @State + ArrayList children; + @State + int mChildrenStartingIndex = 0; + @State + boolean loadMoreChildrenSuccess = true; + @State + boolean hasMoreChildren; + @State + String mMessageFullname; + @State + String mNewAccountName; + + private boolean showToast = false; + + private LinearLayoutManager mLinearLayoutManager; + private CommentAndPostRecyclerViewAdapter mAdapter; + + @BindView(R.id.coordinator_layout_view_post_detail) CoordinatorLayout mCoordinatorLayout; + @BindView(R.id.appbar_layout_view_post_detail_activity) AppBarLayout appBarLayout; + @BindView(R.id.toolbar_view_post_detail_activity) Toolbar toolbar; + @BindView(R.id.progress_bar_view_post_detail_activity) ProgressBar mProgressBar; + @BindView(R.id.recycler_view_view_post_detail) RecyclerView mRecyclerView; + @BindView(R.id.fetch_post_info_linear_layout_view_post_detail_activity) LinearLayout mFetchPostInfoLinearLayout; + @BindView(R.id.fetch_post_info_image_view_view_post_detail_activity) ImageView mFetchPostInfoImageView; + @BindView(R.id.fetch_post_info_text_view_view_post_detail_activity) TextView mFetchPostInfoTextView; + + @Inject @Named("no_oauth") + Retrofit mRetrofit; + + @Inject @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_view_post_detail); + + Bridge.restoreInstanceState(this, savedInstanceState); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + Resources resources = getResources(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 + && (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT + || resources.getBoolean(R.bool.isTablet))) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + + boolean lightNavBar = false; + if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + lightNavBar = true; + } + boolean finalLightNavBar = lightNavBar; + + View decorView = window.getDecorView(); + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, State state) { + if (state == State.COLLAPSED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } else if (state == State.EXPANDED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } + } + }); + + int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (statusBarResourceId > 0) { + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); + params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); + toolbar.setLayoutParams(params); + } + + int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); + if (navBarResourceId > 0) { + mRecyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); + showToast = true; + } + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + toolbar.setTitle(""); + setSupportActionBar(toolbar); + + mNeedBlurNsfw = mSharedPreferences.getBoolean(SharedPreferencesUtils.BLUR_NSFW_KEY, true); + mNeedBlurSpoiler = mSharedPreferences.getBoolean(SharedPreferencesUtils.BLUR_SPOILER_KEY, false); + + mGlide = Glide.with(this); + mLocale = getResources().getConfiguration().locale; + + mLinearLayoutManager = new LinearLayoutManager(this); + mRecyclerView.setLayoutManager(mLinearLayoutManager); + + mSingleCommentId = getIntent().hasExtra(EXTRA_SINGLE_COMMENT_ID) ? getIntent().getExtras().getString(EXTRA_SINGLE_COMMENT_ID) : null; + if(savedInstanceState == null) { + if(mSingleCommentId != null) { + isSingleCommentThreadMode = true; + } + mMessageFullname = getIntent().getStringExtra(EXTRA_MESSAGE_FULLNAME); + mNewAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); + } + + orientation = getResources().getConfiguration().orientation; + + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccountAndBindView(); + } else { + bindView(); + } + + if(getIntent().hasExtra(EXTRA_POST_LIST_POSITION)) { + postListPosition = getIntent().getIntExtra(EXTRA_POST_LIST_POSITION, -1); + } + } + + private void getCurrentAccountAndBindView() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(mNewAccountName != null) { + if(account == null || !account.getUsername().equals(mNewAccountName)) { + new SwitchAccountAsyncTask(mRedditDataRoomDatabase, mNewAccountName, newAccount -> { + EventBus.getDefault().post(new SwitchAccountEvent(getClass().getName())); + Toast.makeText(this, R.string.account_switched, Toast.LENGTH_SHORT).show(); + + mNewAccountName = null; + if(newAccount == null) { + mNullAccessToken = true; + } else { + mAccessToken = newAccount.getAccessToken(); + mAccountName = newAccount.getUsername(); + } + + bindView(); + }).execute(); + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + bindView(); + } + } else { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + + bindView(); + } + }).execute(); + } + + private void bindView() { + if(mAccessToken != null && mMessageFullname != null) { + ReadMessage.readMessage(mOauthRetrofit, mAccessToken, mMessageFullname, new ReadMessage.ReadMessageListener() { + @Override + public void readSuccess() { + mMessageFullname = null; + } + + @Override + public void readFailed() { + + } + }); + } + + if(mPost == null) { + mPost = getIntent().getParcelableExtra(EXTRA_POST_DATA); + } + + if(mPost == null) { + fetchPostAndCommentsById(getIntent().getStringExtra(EXTRA_POST_ID)); + } else { + if(mMenu != null) { + MenuItem saveItem = mMenu.findItem(R.id.action_save_view_post_detail_activity); + MenuItem hideItem = mMenu.findItem(R.id.action_hide_view_post_detail_activity); + + mMenu.findItem(R.id.action_comment_view_post_detail_activity).setVisible(true); + + if(mAccessToken != null) { + if(mPost.isSaved()) { + saveItem.setVisible(true); + saveItem.setIcon(R.drawable.ic_baseline_bookmark_24px); + } else { + saveItem.setVisible(true); + saveItem.setIcon(R.drawable.ic_baseline_bookmark_border_24px); + } + + if(mPost.isHidden()) { + hideItem.setVisible(true); + hideItem.setTitle(R.string.action_unhide_post); + } else { + hideItem.setVisible(true); + hideItem.setTitle(R.string.action_hide_post); + } + } else { + saveItem.setVisible(false); + hideItem.setVisible(false); + } + + if(mPost.getAuthor().equals(mAccountName)) { + if(mPost.getPostType() == Post.TEXT_TYPE) { + mMenu.findItem(R.id.action_edit_view_post_detail_activity).setVisible(true); + } + mMenu.findItem(R.id.action_delete_view_post_detail_activity).setVisible(true); + + MenuItem nsfwItem = mMenu.findItem(R.id.action_nsfw_view_post_detail_activity); + nsfwItem.setVisible(true); + if(mPost.isNSFW()) { + nsfwItem.setTitle(R.string.action_unmark_nsfw); + } else { + nsfwItem.setTitle(R.string.action_mark_nsfw); + } + + MenuItem spoilerItem = mMenu.findItem(R.id.action_spoiler_view_post_detail_activity); + spoilerItem.setVisible(true); + if(mPost.isSpoiler()) { + spoilerItem.setTitle(R.string.action_unmark_spoiler); + } else { + spoilerItem.setTitle(R.string.action_mark_spoiler); + } + + mMenu.findItem(R.id.action_edit_flair_view_post_detail_activity).setVisible(true); + } + + mMenu.findItem(R.id.action_view_crosspost_parent_view_post_detail_activity).setVisible(mPost.getCrosspostParentId() != null); + } + + mAdapter = new CommentAndPostRecyclerViewAdapter(ViewPostDetailActivity.this, mRetrofit, + mOauthRetrofit, mRedditDataRoomDatabase, mGlide, mAccessToken, mAccountName, mPost, + mLocale, mSingleCommentId, isSingleCommentThreadMode, mNeedBlurNsfw, mNeedBlurSpoiler, + new CommentAndPostRecyclerViewAdapter.CommentRecyclerViewAdapterCallback() { + @Override + public void updatePost(Post post) { + EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); + } + + @Override + public void retryFetchingComments() { + fetchComments(false); + } + + @Override + public void retryFetchingMoreComments() { + isLoadingMoreChildren = false; + loadMoreChildrenSuccess = true; + + fetchMoreComments(); + } + }); + mRecyclerView.setAdapter(mAdapter); + + if(comments == null) { + fetchComments(false); + } else { + if(isRefreshing) { + isRefreshing = false; + refresh(true, true); + } else { + mAdapter.addComments(comments, hasMoreChildren); + if(isLoadingMoreChildren) { + isLoadingMoreChildren = false; + fetchMoreComments(); + } + } + } + } + } + + + private void fetchPostAndCommentsById(String subredditId) { + mFetchPostInfoLinearLayout.setVisibility(View.GONE); + mProgressBar.setVisibility(View.VISIBLE); + mGlide.clear(mFetchPostInfoImageView); + + Call postAndComments; + if(mAccessToken == null) { + if(isSingleCommentThreadMode && mSingleCommentId != null) { + postAndComments = mRetrofit.create(RedditAPI.class).getPostAndCommentsSingleThreadById(subredditId, mSingleCommentId); + } else { + postAndComments = mRetrofit.create(RedditAPI.class).getPostAndCommentsById(subredditId); + } + } else { + if(isSingleCommentThreadMode && mSingleCommentId != null) { + postAndComments = mOauthRetrofit.create(RedditAPI.class).getPostAndCommentsSingleThreadByIdOauth(subredditId, + mSingleCommentId, RedditUtils.getOAuthHeader(mAccessToken)); + } else { + postAndComments = mOauthRetrofit.create(RedditAPI.class).getPostAndCommentsByIdOauth(subredditId, + RedditUtils.getOAuthHeader(mAccessToken)); + } + } + postAndComments.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + mProgressBar.setVisibility(View.GONE); + + if(response.isSuccessful()) { + ParsePost.parsePost(response.body(), mLocale, new ParsePost.ParsePostListener() { + @Override + public void onParsePostSuccess(Post post) { + mPost = post; + + if(mMenu != null) { + MenuItem saveItem = mMenu.findItem(R.id.action_save_view_post_detail_activity); + MenuItem hideItem = mMenu.findItem(R.id.action_hide_view_post_detail_activity); + + mMenu.findItem(R.id.action_comment_view_post_detail_activity).setVisible(true); + + if(mAccessToken != null) { + if(post.isSaved()) { + saveItem.setVisible(true); + saveItem.setIcon(R.drawable.ic_baseline_bookmark_24px); + } else { + saveItem.setVisible(true); + saveItem.setIcon(R.drawable.ic_baseline_bookmark_border_24px); + } + + if(post.isHidden()) { + hideItem.setVisible(true); + hideItem.setTitle(R.string.action_unhide_post); + } else { + hideItem.setVisible(true); + hideItem.setTitle(R.string.action_hide_post); + } + } else { + saveItem.setVisible(false); + hideItem.setVisible(false); + } + + if(mPost.getAuthor().equals(mAccountName)) { + if(mPost.getPostType() == Post.TEXT_TYPE) { + mMenu.findItem(R.id.action_edit_view_post_detail_activity).setVisible(true); + } + mMenu.findItem(R.id.action_delete_view_post_detail_activity).setVisible(true); + } + + mMenu.findItem(R.id.action_view_crosspost_parent_view_post_detail_activity).setVisible(mPost.getCrosspostParentId() != null); + } + + mAdapter = new CommentAndPostRecyclerViewAdapter(ViewPostDetailActivity.this, + mRetrofit, mOauthRetrofit, mRedditDataRoomDatabase, mGlide, + mAccessToken, mAccountName, mPost, mLocale, mSingleCommentId, + isSingleCommentThreadMode, mNeedBlurNsfw, mNeedBlurSpoiler, + new CommentAndPostRecyclerViewAdapter.CommentRecyclerViewAdapterCallback() { + @Override + public void updatePost(Post post) { + EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); + } + + @Override + public void retryFetchingComments() { + fetchComments(false); + } + + @Override + public void retryFetchingMoreComments() { + isLoadingMoreChildren = false; + loadMoreChildrenSuccess = true; + + fetchMoreComments(); + } + }); + mRecyclerView.setAdapter(mAdapter); + + ParseComment.parseComment(response.body(), new ArrayList<>(), mLocale, + new ParseComment.ParseCommentListener() { + @Override + public void onParseCommentSuccess(ArrayList expandedComments, String parentId, ArrayList moreChildrenFullnames) { + ViewPostDetailActivity.this.children = moreChildrenFullnames; + + hasMoreChildren = children.size() != 0; + mAdapter.addComments(expandedComments, hasMoreChildren); + + if(children.size() > 0) { + mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + + if(!isLoadingMoreChildren && loadMoreChildrenSuccess) { + int visibleItemCount = mLinearLayoutManager.getChildCount(); + int totalItemCount = mLinearLayoutManager.getItemCount(); + int firstVisibleItemPosition = mLinearLayoutManager.findFirstVisibleItemPosition(); + + if ((visibleItemCount + firstVisibleItemPosition >= totalItemCount) && firstVisibleItemPosition >= 0) { + fetchMoreComments(); + } + } + } + }); + } + } + + @Override + public void onParseCommentFailed() { + mAdapter.initiallyLoadCommentsFailed(); + } + }); + } + + @Override + public void onParsePostFail() { + showErrorView(subredditId); + } + }); + } else { + showErrorView(subredditId); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + showErrorView(subredditId); + } + }); + } + + private void fetchComments(boolean changeRefreshState) { + mAdapter.setSingleComment(mSingleCommentId, isSingleCommentThreadMode); + mAdapter.initiallyLoading(); + String commentId = null; + if(isSingleCommentThreadMode) { + commentId = mSingleCommentId; + } + + Retrofit retrofit = mAccessToken == null ? mRetrofit : mOauthRetrofit; + FetchComment.fetchComments(retrofit, mAccessToken, mPost.getId(), commentId, mLocale, new FetchComment.FetchCommentListener() { + @Override + public void onFetchCommentSuccess(ArrayList expandedComments, + String parentId, ArrayList children) { + ViewPostDetailActivity.this.children = children; + + comments = expandedComments; + hasMoreChildren = children.size() != 0; + mAdapter.addComments(expandedComments, hasMoreChildren); + + if(children.size() > 0) { + mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + + if(!isLoadingMoreChildren && loadMoreChildrenSuccess) { + int visibleItemCount = mLinearLayoutManager.getChildCount(); + int totalItemCount = mLinearLayoutManager.getItemCount(); + int firstVisibleItemPosition = mLinearLayoutManager.findFirstVisibleItemPosition(); + + if ((visibleItemCount + firstVisibleItemPosition >= totalItemCount) && firstVisibleItemPosition >= 0) { + fetchMoreComments(); + } + } + } + }); + } + if(changeRefreshState) { + isRefreshing = false; + } + } + + @Override + public void onFetchCommentFailed() { + mAdapter.initiallyLoadCommentsFailed(); + if(changeRefreshState) { + isRefreshing = false; + } + } + }); + } + + void fetchMoreComments() { + if(isLoadingMoreChildren || !loadMoreChildrenSuccess) { + return; + } + + isLoadingMoreChildren = true; + + Retrofit retrofit = mAccessToken == null ? mRetrofit : mOauthRetrofit; + FetchComment.fetchMoreComment(retrofit, mAccessToken, children, mChildrenStartingIndex, + 0, mLocale, new FetchComment.FetchMoreCommentListener() { + @Override + public void onFetchMoreCommentSuccess(ArrayList expandedComments, int childrenStartingIndex) { + hasMoreChildren = childrenStartingIndex < children.size(); + mAdapter.addComments(expandedComments, hasMoreChildren); + mChildrenStartingIndex = childrenStartingIndex; + isLoadingMoreChildren = false; + loadMoreChildrenSuccess = true; + } + + @Override + public void onFetchMoreCommentFailed() { + isLoadingMoreChildren = false; + loadMoreChildrenSuccess = false; + mAdapter.loadMoreCommentsFailed(); + } + }); + } + + private void refresh(boolean fetchPost, boolean fetchComments) { + if(!isRefreshing) { + isRefreshing = true; + mChildrenStartingIndex = 0; + + mFetchPostInfoLinearLayout.setVisibility(View.GONE); + mGlide.clear(mFetchPostInfoImageView); + + if(fetchComments) { + if(!fetchPost) { + fetchComments(true); + } else { + fetchComments(false); + } + } + + if(fetchPost) { + Retrofit retrofit; + if(mAccessToken == null) { + retrofit = mRetrofit; + } else { + retrofit = mOauthRetrofit; + } + FetchPost.fetchPost(retrofit, mPost.getId(), mAccessToken, mLocale, + new FetchPost.FetchPostListener() { + @Override + public void fetchPostSuccess(Post post) { + mPost = post; + mAdapter.updatePost(mPost); + EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); + isRefreshing = false; + if(mMenu != null) { + MenuItem saveItem = mMenu.findItem(R.id.action_save_view_post_detail_activity); + MenuItem hideItem = mMenu.findItem(R.id.action_hide_view_post_detail_activity); + + mMenu.findItem(R.id.action_comment_view_post_detail_activity).setVisible(true); + + if(mAccessToken != null) { + if(post.isSaved()) { + saveItem.setVisible(true); + saveItem.setIcon(R.drawable.ic_baseline_bookmark_24px); + } else { + saveItem.setVisible(true); + saveItem.setIcon(R.drawable.ic_baseline_bookmark_border_24px); + } + + if(post.isHidden()) { + hideItem.setVisible(true); + hideItem.setTitle(R.string.action_unhide_post); + } else { + hideItem.setVisible(true); + hideItem.setTitle(R.string.action_hide_post); + } + } else { + saveItem.setVisible(false); + hideItem.setVisible(false); + } + + mMenu.findItem(R.id.action_view_crosspost_parent_view_post_detail_activity).setVisible(mPost.getCrosspostParentId() != null); + } + } + + @Override + public void fetchPostFailed() { + showMessage(R.string.refresh_post_failed); + isRefreshing = false; + } + }); + } + } + } + + private void showErrorView(String subredditId) { + mProgressBar.setVisibility(View.GONE); + mFetchPostInfoLinearLayout.setVisibility(View.VISIBLE); + mFetchPostInfoLinearLayout.setOnClickListener(view -> fetchPostAndCommentsById(subredditId)); + mFetchPostInfoTextView.setText(R.string.load_post_error); + mGlide.load(R.drawable.error_image).into(mFetchPostInfoImageView); + } + + private void showMessage(int resId) { + if(showToast) { + Toast.makeText(ViewPostDetailActivity.this, resId, Toast.LENGTH_SHORT).show(); + } else { + Snackbar.make(mCoordinatorLayout, resId, Snackbar.LENGTH_SHORT).show(); + } + } + + private void markNSFW() { + if(mMenu != null) { + mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_unmark_nsfw); + } + + Map params = new HashMap<>(); + params.put(RedditUtils.ID_KEY, mPost.getFullName()); + mOauthRetrofit.create(RedditAPI.class).markNSFW(RedditUtils.getOAuthHeader(mAccessToken), params) + .enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if(response.isSuccessful()) { + if(mMenu != null) { + mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_unmark_nsfw); + } + + refresh(true, false); + showMessage(R.string.mark_nsfw_success); + } else { + if(mMenu != null) { + mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_mark_nsfw); + } + + showMessage(R.string.mark_nsfw_failed); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + if(mMenu != null) { + mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_mark_nsfw); + } + + showMessage(R.string.mark_nsfw_failed); + } + }); + } + + private void unmarkNSFW() { + if(mMenu != null) { + mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_mark_nsfw); + } + + Map params = new HashMap<>(); + params.put(RedditUtils.ID_KEY, mPost.getFullName()); + mOauthRetrofit.create(RedditAPI.class).unmarkNSFW(RedditUtils.getOAuthHeader(mAccessToken), params) + .enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if(response.isSuccessful()) { + if(mMenu != null) { + mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_mark_nsfw); + } + + refresh(true, false); + showMessage(R.string.unmark_nsfw_success); + } else { + if(mMenu != null) { + mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_unmark_nsfw); + } + + showMessage(R.string.unmark_nsfw_failed); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + if(mMenu != null) { + mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_unmark_nsfw); + } + + showMessage(R.string.unmark_nsfw_failed); + } + }); + } + + private void markSpoiler() { + if(mMenu != null) { + mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_unmark_spoiler); + } + + Map params = new HashMap<>(); + params.put(RedditUtils.ID_KEY, mPost.getFullName()); + mOauthRetrofit.create(RedditAPI.class).markSpoiler(RedditUtils.getOAuthHeader(mAccessToken), params) + .enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if(response.isSuccessful()) { + if(mMenu != null) { + mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_unmark_spoiler); + } + + refresh(true, false); + showMessage(R.string.mark_spoiler_success); + } else { + if(mMenu != null) { + mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_mark_spoiler); + } + + showMessage(R.string.mark_spoiler_failed); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + if(mMenu != null) { + mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_mark_spoiler); + } + + showMessage(R.string.mark_spoiler_failed); + } + }); + } + + private void unmarkSpoiler() { + if(mMenu != null) { + mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_mark_spoiler); + } + + Map params = new HashMap<>(); + params.put(RedditUtils.ID_KEY, mPost.getFullName()); + mOauthRetrofit.create(RedditAPI.class).unmarkSpoiler(RedditUtils.getOAuthHeader(mAccessToken), params) + .enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if(response.isSuccessful()) { + if(mMenu != null) { + mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_mark_spoiler); + } + + refresh(true, false); + showMessage(R.string.unmark_spoiler_success); + } else { + if(mMenu != null) { + mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_unmark_spoiler); + } + + showMessage(R.string.unmark_spoiler_failed); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + if(mMenu != null) { + mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_unmark_spoiler); + } + + showMessage(R.string.unmark_spoiler_failed); + } + }); + } + + public void deleteComment(String fullName, int position) { + new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme) + .setTitle(R.string.delete_this_comment) + .setMessage(R.string.are_you_sure) + .setPositiveButton(R.string.delete, (dialogInterface, i) + -> DeleteThing.delete(mOauthRetrofit, fullName, mAccessToken, new DeleteThing.DeleteThingListener() { + @Override + public void deleteSuccess() { + Toast.makeText(ViewPostDetailActivity.this, R.string.delete_post_success, Toast.LENGTH_SHORT).show(); + mAdapter.deleteComment(position); + } + + @Override + public void deleteFailed() { + Toast.makeText(ViewPostDetailActivity.this, R.string.delete_post_failed, Toast.LENGTH_SHORT).show(); + } + })) + .setNegativeButton(R.string.cancel, null) + .show(); + } + + public void changeToSingleThreadMode() { + isSingleCommentThreadMode = false; + mSingleCommentId = null; + refresh(false, true); + } + + @Subscribe + public void onPostUpdateEvent(PostUpdateEventToDetailActivity event) { + if(mPost.getId().equals(event.post.getId())) { + mPost.setVoteType(event.post.getVoteType()); + mPost.setSaved(event.post.isSaved()); + if(mMenu != null) { + if(event.post.isSaved()) { + mMenu.findItem(R.id.action_save_view_post_detail_activity).setIcon(getResources() + .getDrawable(R.drawable.ic_baseline_bookmark_24px)); + } else { + mMenu.findItem(R.id.action_save_view_post_detail_activity).setIcon(getResources() + .getDrawable(R.drawable.ic_baseline_bookmark_border_24px)); + } + } + mAdapter.updatePost(mPost); + } + } + + @Subscribe + public void onChangeNSFWBlurEvent(ChangeNSFWBlurEvent event) { + mAdapter.setBlurNSFW(event.needBlurNSFW); + refreshAdapter(); + } + + @Subscribe + public void onChangeSpoilerBlurEvent(ChangeSpoilerBlurEvent event) { + mAdapter.setBlurSpoiler(event.needBlurSpoiler); + refreshAdapter(); + } + + private void refreshAdapter() { + int previousPosition = -1; + if(mLinearLayoutManager != null) { + previousPosition = mLinearLayoutManager.findFirstVisibleItemPosition(); + } + + RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager(); + mRecyclerView.setAdapter(null); + mRecyclerView.setLayoutManager(null); + mRecyclerView.setAdapter(mAdapter); + mRecyclerView.setLayoutManager(layoutManager); + + if(previousPosition > 0) { + mRecyclerView.scrollToPosition(previousPosition); + } + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + if(!getClass().getName().equals(event.excludeActivityClassName)) { + finish(); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.view_post_detail_activity, menu); + mMenu = menu; + if(mPost != null) { + MenuItem saveItem = mMenu.findItem(R.id.action_save_view_post_detail_activity); + MenuItem hideItem = mMenu.findItem(R.id.action_hide_view_post_detail_activity); + + mMenu.findItem(R.id.action_comment_view_post_detail_activity).setVisible(true); + + if(mAccessToken != null) { + if(mPost.isSaved()) { + saveItem.setVisible(true); + saveItem.setIcon(R.drawable.ic_baseline_bookmark_24px); + } else { + saveItem.setVisible(true); + saveItem.setIcon(R.drawable.ic_baseline_bookmark_border_24px); + } + + if(mPost.isHidden()) { + hideItem.setVisible(true); + hideItem.setTitle(R.string.action_unhide_post); + } else { + hideItem.setVisible(true); + hideItem.setTitle(R.string.action_hide_post); + } + } else { + saveItem.setVisible(false); + hideItem.setVisible(false); + } + + if(mPost.getAuthor().equals(mAccountName)) { + if(mPost.getPostType() == Post.TEXT_TYPE) { + menu.findItem(R.id.action_edit_view_post_detail_activity).setVisible(true); + } + menu.findItem(R.id.action_delete_view_post_detail_activity).setVisible(true); + + MenuItem nsfwItem = menu.findItem(R.id.action_nsfw_view_post_detail_activity); + nsfwItem.setVisible(true); + if(mPost.isNSFW()) { + nsfwItem.setTitle(R.string.action_unmark_nsfw); + } else { + nsfwItem.setTitle(R.string.action_mark_nsfw); + } + + MenuItem spoilerItem = menu.findItem(R.id.action_spoiler_view_post_detail_activity); + spoilerItem.setVisible(true); + if(mPost.isSpoiler()) { + spoilerItem.setTitle(R.string.action_unmark_spoiler); + } else { + spoilerItem.setTitle(R.string.action_mark_spoiler); + } + + menu.findItem(R.id.action_edit_flair_view_post_detail_activity).setVisible(true); + } + + menu.findItem(R.id.action_view_crosspost_parent_view_post_detail_activity).setVisible(mPost.getCrosspostParentId() != null); + } + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case R.id.action_refresh_view_post_detail_activity: + refresh(true, true); + return true; + case R.id.action_comment_view_post_detail_activity: + if(mPost != null) { + if(mPost.isArchived()) { + showMessage(R.string.archived_post_reply_unavailable); + return true; + } + + if(mPost.isLocked()) { + showMessage(R.string.locked_post_comment_unavailable); + return true; + } + + if(mAccessToken == null) { + showMessage(R.string.login_first); + return true; + } + + Intent intent = new Intent(this, CommentActivity.class); + intent.putExtra(CommentActivity.EXTRA_COMMENT_PARENT_TEXT_KEY, mPost.getTitle()); + intent.putExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY, mPost.getFullName()); + intent.putExtra(CommentActivity.EXTRA_PARENT_DEPTH_KEY, 0); + intent.putExtra(CommentActivity.EXTRA_IS_REPLYING_KEY, false); + startActivityForResult(intent, WRITE_COMMENT_REQUEST_CODE); + } + return true; + case R.id.action_save_view_post_detail_activity: + if(mPost != null && mAccessToken != null) { + if(mPost.isSaved()) { + item.setIcon(R.drawable.ic_baseline_bookmark_border_24px); + SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, mPost.getFullName(), + new SaveThing.SaveThingListener() { + @Override + public void success() { + mPost.setSaved(false); + item.setIcon(R.drawable.ic_baseline_bookmark_border_24px); + showMessage(R.string.post_unsaved_success); + EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); + } + + @Override + public void failed() { + mPost.setSaved(true); + item.setIcon(R.drawable.ic_baseline_bookmark_24px); + showMessage(R.string.post_unsaved_failed); + EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); + } + }); + } else { + item.setIcon(R.drawable.ic_baseline_bookmark_24px); + SaveThing.saveThing(mOauthRetrofit, mAccessToken, mPost.getFullName(), + new SaveThing.SaveThingListener() { + @Override + public void success() { + mPost.setSaved(true); + item.setIcon(R.drawable.ic_baseline_bookmark_24px); + showMessage(R.string.post_saved_success); + EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); + } + + @Override + public void failed() { + mPost.setSaved(false); + item.setIcon(R.drawable.ic_baseline_bookmark_border_24px); + showMessage(R.string.post_saved_failed); + EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); + } + }); + } + } + return true; + case R.id.action_view_crosspost_parent_view_post_detail_activity: + Intent crosspostIntent = new Intent(this, ViewPostDetailActivity.class); + crosspostIntent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, mPost.getCrosspostParentId()); + startActivity(crosspostIntent); + return true; + case R.id.action_hide_view_post_detail_activity: + if(mPost != null && mAccessToken != null) { + if(mPost.isHidden()) { + item.setTitle(R.string.action_hide_post); + + HidePost.unhidePost(mOauthRetrofit, mAccessToken, mPost.getFullName(), new HidePost.HidePostListener() { + @Override + public void success() { + mPost.setHidden(false); + item.setTitle(R.string.action_hide_post); + showMessage(R.string.post_unhide_success); + EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); + } + + @Override + public void failed() { + mPost.setHidden(true); + item.setTitle(R.string.action_unhide_post); + showMessage(R.string.post_unhide_failed); + EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); + } + }); + } else { + item.setTitle(R.string.action_unhide_post); + + HidePost.hidePost(mOauthRetrofit, mAccessToken, mPost.getFullName(), new HidePost.HidePostListener() { + @Override + public void success() { + mPost.setHidden(true); + item.setTitle(R.string.action_unhide_post); + showMessage(R.string.post_hide_success); + EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); + } + + @Override + public void failed() { + mPost.setHidden(false); + item.setTitle(R.string.action_hide_post); + showMessage(R.string.post_hide_failed); + EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); + } + }); + } + } + return true; + case R.id.action_edit_view_post_detail_activity: + Intent editPostItent = new Intent(this, EditPostActivity.class); + editPostItent.putExtra(EditPostActivity.EXTRA_ACCESS_TOKEN, mAccessToken); + editPostItent.putExtra(EditPostActivity.EXTRA_FULLNAME, mPost.getFullName()); + editPostItent.putExtra(EditPostActivity.EXTRA_TITLE, mPost.getTitle()); + editPostItent.putExtra(EditPostActivity.EXTRA_CONTENT, mPost.getSelfText()); + startActivityForResult(editPostItent, EDIT_POST_REQUEST_CODE); + return true; + case R.id.action_delete_view_post_detail_activity: + new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme) + .setTitle(R.string.delete_this_post) + .setMessage(R.string.are_you_sure) + .setPositiveButton(R.string.delete, (dialogInterface, i) + -> DeleteThing.delete(mOauthRetrofit, mPost.getFullName(), mAccessToken, new DeleteThing.DeleteThingListener() { + @Override + public void deleteSuccess() { + Toast.makeText(ViewPostDetailActivity.this, R.string.delete_post_success, Toast.LENGTH_SHORT).show(); + finish(); + } + + @Override + public void deleteFailed() { + showMessage(R.string.delete_post_failed); + } + })) + .setNegativeButton(R.string.cancel, null) + .show(); + return true; + case R.id.action_nsfw_view_post_detail_activity: + if(mPost.isNSFW()) { + unmarkNSFW(); + } else { + markNSFW(); + } + return true; + case R.id.action_spoiler_view_post_detail_activity: + if(mPost.isSpoiler()) { + unmarkSpoiler(); + } else { + markSpoiler(); + } + return true; + case R.id.action_edit_flair_view_post_detail_activity: + FlairBottomSheetFragment flairBottomSheetFragment = new FlairBottomSheetFragment(); + Bundle bundle = new Bundle(); + bundle.putString(FlairBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + bundle.putString(FlairBottomSheetFragment.EXTRA_SUBREDDIT_NAME, mPost.getSubredditName()); + flairBottomSheetFragment.setArguments(bundle); + flairBottomSheetFragment.show(getSupportFragmentManager(), flairBottomSheetFragment.getTag()); + return true; + case android.R.id.home: + onBackPressed(); + return true; + } + return false; + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if(requestCode == WRITE_COMMENT_REQUEST_CODE) { + if(data != null && resultCode == RESULT_OK) { + if(data.hasExtra(EXTRA_COMMENT_DATA_KEY)) { + CommentData comment = data.getParcelableExtra(EXTRA_COMMENT_DATA_KEY); + if(comment != null && comment.getDepth() == 0) { + mAdapter.addComment(comment); + } else { + String parentFullname = data.getStringExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY); + int parentPosition = data.getIntExtra(CommentActivity.EXTRA_PARENT_POSITION_KEY, -1); + if(parentFullname != null && parentPosition >= 0) { + mAdapter.addChildComment(comment, parentFullname, parentPosition); + } + } + } else { + Toast.makeText(this, R.string.send_comment_failed, Toast.LENGTH_SHORT).show(); + } + } + } else if(requestCode == EDIT_POST_REQUEST_CODE) { + if(resultCode == RESULT_OK) { + refresh(true, false); + } + } else if(requestCode == EDIT_COMMENT_REQUEST_CODE) { + if(resultCode == RESULT_OK) { + mAdapter.editComment(data.getStringExtra(EditCommentActivity.EXTRA_EDITED_COMMENT_CONTENT), + data.getExtras().getInt(EditCommentActivity.EXTRA_EDITED_COMMENT_POSITION)); + } + } + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + comments = mAdapter == null ? null : mAdapter.getVisibleComments(); + Bridge.saveInstanceState(this, outState); + } + + @Override + public void onBackPressed() { + if(orientation == getResources().getConfiguration().orientation) { + super.onBackPressed(); + } else { + finish(); + } + } + + @Override + protected void onDestroy() { + EventBus.getDefault().unregister(this); + super.onDestroy(); + Bridge.clear(this); + } + + @Override + public void flairSelected(Flair flair) { + Map params = new HashMap<>(); + params.put(RedditUtils.API_TYPE_KEY, RedditUtils.API_TYPE_JSON); + params.put(RedditUtils.FLAIR_TEMPLATE_ID_KEY, flair.getId()); + params.put(RedditUtils.LINK_KEY, mPost.getFullName()); + params.put(RedditUtils.TEXT_KEY, flair.getText()); + + mOauthRetrofit.create(RedditAPI.class).selectFlair(mPost.getSubredditNamePrefixed(), + RedditUtils.getOAuthHeader(mAccessToken), params).enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if(response.isSuccessful()) { + refresh(true, false); + showMessage(R.string.update_flair_success); + } else { + showMessage(R.string.update_flair_failed); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + showMessage(R.string.update_flair_failed); + } + }); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java new file mode 100644 index 00000000..d4661f47 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java @@ -0,0 +1,676 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.request.RequestOptions; +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.appbar.CollapsingToolbarLayout; +import com.google.android.material.chip.Chip; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.google.android.material.snackbar.Snackbar; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; +import ml.docilealligator.infinityforreddit.AsyncTask.CheckIsSubscribedToSubredditAsyncTask; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.AsyncTask.SwitchAccountAsyncTask; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.Event.ChangeNSFWEvent; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.FetchSubredditData; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.Fragment.PostFragment; +import ml.docilealligator.infinityforreddit.Fragment.PostTypeBottomSheetFragment; +import ml.docilealligator.infinityforreddit.Fragment.SortTypeBottomSheetFragment; +import ml.docilealligator.infinityforreddit.FragmentCommunicator; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.ReadMessage; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditDao; +import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditData; +import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditViewModel; +import ml.docilealligator.infinityforreddit.SubredditSubscription; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import pl.droidsonroids.gif.GifImageView; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class ViewSubredditDetailActivity extends AppCompatActivity implements SortTypeBottomSheetFragment.SortTypeSelectionCallback, + PostTypeBottomSheetFragment.PostTypeSelectionCallback { + + public static final String EXTRA_SUBREDDIT_NAME_KEY = "ESN"; + public static final String EXTRA_MESSAGE_FULLNAME = "ENF"; + public static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; + + private static final String FETCH_SUBREDDIT_INFO_STATE = "FSIS"; + private static final String CURRENT_ONLINE_SUBSCRIBERS_STATE = "COSS"; + private static final String FRAGMENT_OUT_STATE_KEY = "FOSK"; + private static final String IS_IN_LAZY_MODE_STATE = "IILMS"; + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + private static final String ACCOUNT_NAME_STATE = "ANS"; + private static final String MESSAGE_FULLNAME_STATE = "MFS"; + private static final String NEW_ACCOUNT_NAME_STATE = "NANS"; + + @BindView(R.id.coordinator_layout_view_subreddit_detail_activity) CoordinatorLayout coordinatorLayout; + @BindView(R.id.appbar_layout_view_subreddit_detail) AppBarLayout appBarLayout; + @BindView(R.id.collapsing_toolbar_layout_view_subreddit_detail_activity) CollapsingToolbarLayout collapsingToolbarLayout; + @BindView(R.id.toolbar) Toolbar toolbar; + @BindView(R.id.banner_image_view_view_subreddit_detail_activity) GifImageView bannerImageView; + @BindView(R.id.icon_gif_image_view_view_subreddit_detail_activity) GifImageView iconGifImageView; + @BindView(R.id.subscribe_subreddit_chip_view_subreddit_detail_activity) Chip subscribeSubredditChip; + @BindView(R.id.subreddit_name_text_view_view_subreddit_detail_activity) TextView subredditNameTextView; + @BindView(R.id.subscriber_count_text_view_view_subreddit_detail_activity) TextView nSubscribersTextView; + @BindView(R.id.online_subscriber_count_text_view_view_subreddit_detail_activity) TextView nOnlineSubscribersTextView; + @BindView(R.id.description_text_view_view_subreddit_detail_activity) TextView descriptionTextView; + @BindView(R.id.fab_view_subreddit_detail_activity) FloatingActionButton fab; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String mAccountName; + private String subredditName; + private boolean mFetchSubredditInfoSuccess = false; + private int mNCurrentOnlineSubscribers = 0; + private boolean subscriptionReady = false; + private boolean isInLazyMode = false; + private boolean showToast = false; + private String mMessageFullname; + private String mNewAccountName; + + private RequestManager glide; + private Fragment mFragment; + private Menu mMenu; + private AppBarLayout.LayoutParams params; + private PostTypeBottomSheetFragment postTypeBottomSheetFragment; + private SortTypeBottomSheetFragment sortTypeBottomSheetFragment; + + private SubredditViewModel mSubredditViewModel; + + @Inject + @Named("no_oauth") + Retrofit mRetrofit; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_view_subreddit_detail); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + Resources resources = getResources(); + + if(resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + + boolean lightNavBar = false; + if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + lightNavBar = true; + } + boolean finalLightNavBar = lightNavBar; + + View decorView = window.getDecorView(); + appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, State state) { + if (state == State.COLLAPSED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } else if (state == State.EXPANDED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } + } + }); + + int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); + if (navBarResourceId > 0) { + CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) fab.getLayoutParams(); + params.bottomMargin = resources.getDimensionPixelSize(navBarResourceId); + fab.setLayoutParams(params); + + showToast = true; + } + } + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + subredditName = getIntent().getStringExtra(EXTRA_SUBREDDIT_NAME_KEY); + + if(savedInstanceState == null) { + mMessageFullname = getIntent().getStringExtra(EXTRA_MESSAGE_FULLNAME); + mNewAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); + getCurrentAccountAndBindView(); + } else { + mFetchSubredditInfoSuccess = savedInstanceState.getBoolean(FETCH_SUBREDDIT_INFO_STATE); + mNCurrentOnlineSubscribers = savedInstanceState.getInt(CURRENT_ONLINE_SUBSCRIBERS_STATE); + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); + isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); + mMessageFullname = savedInstanceState.getString(MESSAGE_FULLNAME_STATE); + mNewAccountName = savedInstanceState.getString(NEW_ACCOUNT_NAME_STATE); + + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccountAndBindView(); + } else { + bindView(false); + mFragment = getSupportFragmentManager().getFragment(savedInstanceState, FRAGMENT_OUT_STATE_KEY); + getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_view_subreddit_detail_activity, mFragment).commit(); + } + + if(mFetchSubredditInfoSuccess) { + nOnlineSubscribersTextView.setText(getString(R.string.online_subscribers_number_detail, mNCurrentOnlineSubscribers)); + } + } + + fetchSubredditData(); + + postTypeBottomSheetFragment = new PostTypeBottomSheetFragment(); + + sortTypeBottomSheetFragment = new SortTypeBottomSheetFragment(); + Bundle bottomSheetBundle = new Bundle(); + bottomSheetBundle.putBoolean(SortTypeBottomSheetFragment.EXTRA_NO_BEST_TYPE, true); + sortTypeBottomSheetFragment.setArguments(bottomSheetBundle); + + params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); + + //Get status bar height + int statusBarHeight = 0; + int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (resourceId > 0) { + statusBarHeight = getResources().getDimensionPixelSize(resourceId); + } + + String title = "r/" + subredditName; + subredditNameTextView.setText(title); + + toolbar.setTitle(title); + ViewGroup.MarginLayoutParams toolbarParams = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); + toolbarParams.topMargin = statusBarHeight; + toolbar.setLayoutParams(toolbarParams); + setSupportActionBar(toolbar); + + glide = Glide.with(this); + + mSubredditViewModel = new ViewModelProvider(this, + new SubredditViewModel.Factory(getApplication(), mRedditDataRoomDatabase, subredditName)) + .get(SubredditViewModel.class); + mSubredditViewModel.getSubredditLiveData().observe(this, subredditData -> { + if(subredditData != null) { + if(subredditData.getBannerUrl().equals("")) { + iconGifImageView.setOnClickListener(view -> { + //Do nothing as it has no image + }); + } else { + glide.load(subredditData.getBannerUrl()).into(bannerImageView); + bannerImageView.setOnClickListener(view -> { + Intent intent = new Intent(ViewSubredditDetailActivity.this, ViewImageActivity.class); + intent.putExtra(ViewImageActivity.TITLE_KEY, title); + intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, subredditData.getBannerUrl()); + intent.putExtra(ViewImageActivity.FILE_NAME_KEY, subredditName + "-banner"); + startActivity(intent); + }); + } + + if(subredditData.getIconUrl().equals("")) { + glide.load(getDrawable(R.drawable.subreddit_default_icon)) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0))) + .into(iconGifImageView); + iconGifImageView.setOnClickListener(view -> { + //Do nothing as it is a default icon + }); + } else { + glide.load(subredditData.getIconUrl()) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0))) + .error(glide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0)))) + .into(iconGifImageView); + iconGifImageView.setOnClickListener(view -> { + Intent intent = new Intent(ViewSubredditDetailActivity.this, ViewImageActivity.class); + intent.putExtra(ViewImageActivity.TITLE_KEY, title); + intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, subredditData.getIconUrl()); + intent.putExtra(ViewImageActivity.FILE_NAME_KEY, subredditName + "-icon"); + startActivity(intent); + }); + } + + String subredditFullName = "r/" + subredditData.getName(); + if(!title.equals(subredditFullName)) { + getSupportActionBar().setTitle(subredditFullName); + } + subredditNameTextView.setText(subredditFullName); + String nSubscribers = getString(R.string.subscribers_number_detail, subredditData.getNSubscribers()); + nSubscribersTextView.setText(nSubscribers); + if(subredditData.getDescription().equals("")) { + descriptionTextView.setVisibility(View.GONE); + } else { + descriptionTextView.setVisibility(View.VISIBLE); + descriptionTextView.setText(subredditData.getDescription()); + } + } + }); + + fab.setOnClickListener(view -> { + if(mAccessToken == null) { + Toast.makeText(ViewSubredditDetailActivity.this, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + postTypeBottomSheetFragment.show(getSupportFragmentManager(), postTypeBottomSheetFragment.getTag()); + }); + } + + private void getCurrentAccountAndBindView() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(mNewAccountName != null) { + if(account == null || !account.getUsername().equals(mNewAccountName)) { + new SwitchAccountAsyncTask(mRedditDataRoomDatabase, mNewAccountName, newAccount -> { + EventBus.getDefault().post(new SwitchAccountEvent(getClass().getName())); + Toast.makeText(this, R.string.account_switched, Toast.LENGTH_SHORT).show(); + + mNewAccountName = null; + if(newAccount == null) { + mNullAccessToken = true; + } else { + mAccessToken = newAccount.getAccessToken(); + mAccountName = newAccount.getUsername(); + } + + bindView(true); + }).execute(); + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + bindView(true); + } + } else { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + + bindView(true); + } + }).execute(); + } + + private void fetchSubredditData() { + if(!mFetchSubredditInfoSuccess) { + FetchSubredditData.fetchSubredditData(mRetrofit, subredditName, new FetchSubredditData.FetchSubredditDataListener() { + @Override + public void onFetchSubredditDataSuccess(SubredditData subredditData, int nCurrentOnlineSubscribers) { + mNCurrentOnlineSubscribers = nCurrentOnlineSubscribers; + nOnlineSubscribersTextView.setText(getString(R.string.online_subscribers_number_detail, nCurrentOnlineSubscribers)); + new InsertSubredditDataAsyncTask(mRedditDataRoomDatabase, subredditData, () -> mFetchSubredditInfoSuccess = true).execute(); + } + + @Override + public void onFetchSubredditDataFail() { + makeSnackbar(R.string.cannot_fetch_subreddit_info, true); + mFetchSubredditInfoSuccess = false; + } + }); + } + } + + private void bindView(boolean initializeFragment) { + if(mAccessToken != null && mMessageFullname != null) { + ReadMessage.readMessage(mOauthRetrofit, mAccessToken, mMessageFullname, new ReadMessage.ReadMessageListener() { + @Override + public void readSuccess() { + mMessageFullname = null; + } + + @Override + public void readFailed() { + + } + }); + } + + subscribeSubredditChip.setOnClickListener(view -> { + if(mAccessToken == null) { + Toast.makeText(ViewSubredditDetailActivity.this, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + if(subscriptionReady) { + subscriptionReady = false; + if(subscribeSubredditChip.getText().equals(getResources().getString(R.string.subscribe))) { + SubredditSubscription.subscribeToSubreddit(mOauthRetrofit, mRetrofit, mAccessToken, + subredditName, mAccountName, mRedditDataRoomDatabase, + new SubredditSubscription.SubredditSubscriptionListener() { + @Override + public void onSubredditSubscriptionSuccess() { + subscribeSubredditChip.setText(R.string.unsubscribe); + subscribeSubredditChip.setChipBackgroundColor(getResources().getColorStateList(R.color.colorAccent)); + makeSnackbar(R.string.subscribed, false); + subscriptionReady = true; + } + + @Override + public void onSubredditSubscriptionFail() { + makeSnackbar(R.string.subscribe_failed, false); + subscriptionReady = true; + } + }); + } else { + SubredditSubscription.unsubscribeToSubreddit(mOauthRetrofit, mAccessToken, + subredditName, mAccountName, mRedditDataRoomDatabase, + new SubredditSubscription.SubredditSubscriptionListener() { + @Override + public void onSubredditSubscriptionSuccess() { + subscribeSubredditChip.setText(R.string.subscribe); + subscribeSubredditChip.setChipBackgroundColor(getResources().getColorStateList(R.color.backgroundColorPrimaryDark)); + makeSnackbar(R.string.unsubscribed, false); + subscriptionReady = true; + } + + @Override + public void onSubredditSubscriptionFail() { + makeSnackbar(R.string.unsubscribe_failed, false); + subscriptionReady = true; + } + }); + } + } + }); + + new CheckIsSubscribedToSubredditAsyncTask(mRedditDataRoomDatabase, subredditName, mAccountName, + new CheckIsSubscribedToSubredditAsyncTask.CheckIsSubscribedToSubredditListener() { + @Override + public void isSubscribed() { + subscribeSubredditChip.setText(R.string.unsubscribe); + subscribeSubredditChip.setChipBackgroundColor(getResources().getColorStateList(R.color.colorAccent)); + subscriptionReady = true; + } + + @Override + public void isNotSubscribed() { + subscribeSubredditChip.setText(R.string.subscribe); + subscribeSubredditChip.setChipBackgroundColor(getResources().getColorStateList(R.color.backgroundColorPrimaryDark)); + subscriptionReady = true; + } + }).execute(); + + if(initializeFragment) { + mFragment = new PostFragment(); + Bundle bundle = new Bundle(); + bundle.putString(PostFragment.EXTRA_NAME, subredditName); + bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); + bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_BEST); + bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); + bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + mFragment.setArguments(bundle); + getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_view_subreddit_detail_activity, mFragment).commit(); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.view_subreddit_detail_activity, menu); + mMenu = menu; + MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_view_subreddit_detail_activity); + if(isInLazyMode) { + lazyModeItem.setTitle(R.string.action_stop_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED); + collapsingToolbarLayout.setLayoutParams(params); + } else { + lazyModeItem.setTitle(R.string.action_start_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | + AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED); + collapsingToolbarLayout.setLayoutParams(params); + } + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + case R.id.action_sort_view_subreddit_detail_activity: + sortTypeBottomSheetFragment.show(getSupportFragmentManager(), sortTypeBottomSheetFragment.getTag()); + return true; + case R.id.action_search_view_subreddit_detail_activity: + Intent intent = new Intent(this, SearchActivity.class); + intent.putExtra(SearchActivity.EXTRA_SUBREDDIT_NAME, subredditName); + intent.putExtra(SearchActivity.EXTRA_SUBREDDIT_IS_USER, false); + intent.putExtra(SearchActivity.EXTRA_SEARCH_ONLY_SUBREDDITS, false); + startActivity(intent); + break; + case R.id.action_refresh_view_subreddit_detail_activity: + if(mMenu != null) { + mMenu.findItem(R.id.action_lazy_mode_view_subreddit_detail_activity).setTitle(R.string.action_start_lazy_mode); + } + if(mFragment instanceof FragmentCommunicator) { + ((FragmentCommunicator) mFragment).refresh(); + mFetchSubredditInfoSuccess = false; + fetchSubredditData(); + } + break; + case R.id.action_lazy_mode_view_subreddit_detail_activity: + MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_view_subreddit_detail_activity); + if(isInLazyMode) { + isInLazyMode = false; + ((FragmentCommunicator) mFragment).stopLazyMode(); + lazyModeItem.setTitle(R.string.action_start_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | + AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED); + collapsingToolbarLayout.setLayoutParams(params); + } else { + isInLazyMode = true; + if(((FragmentCommunicator) mFragment).startLazyMode()) { + lazyModeItem.setTitle(R.string.action_stop_lazy_mode); + appBarLayout.setExpanded(false); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED); + collapsingToolbarLayout.setLayoutParams(params); + } else { + isInLazyMode = false; + } + } + } + return false; + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(FETCH_SUBREDDIT_INFO_STATE, mFetchSubredditInfoSuccess); + outState.putInt(CURRENT_ONLINE_SUBSCRIBERS_STATE, mNCurrentOnlineSubscribers); + outState.putBoolean(IS_IN_LAZY_MODE_STATE, isInLazyMode); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putString(ACCOUNT_NAME_STATE, mAccountName); + outState.putString(MESSAGE_FULLNAME_STATE, mMessageFullname); + outState.putString(NEW_ACCOUNT_NAME_STATE, mNewAccountName); + getSupportFragmentManager().putFragment(outState, FRAGMENT_OUT_STATE_KEY, mFragment); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + private void makeSnackbar(int resId, boolean retry) { + if(showToast) { + Toast.makeText(this, resId, Toast.LENGTH_SHORT).show(); + } else { + if(retry) { + Snackbar.make(coordinatorLayout, resId, Snackbar.LENGTH_SHORT).setAction(R.string.retry, + view -> fetchSubredditData()).show(); + } else { + Snackbar.make(coordinatorLayout, resId, Snackbar.LENGTH_SHORT).show(); + } + } + } + + @Override + public void sortTypeSelected(String sortType) { + ((PostFragment) mFragment).changeSortType(sortType); + } + + @Override + public void postTypeSelected(int postType) { + Intent intent; + switch (postType) { + case PostTypeBottomSheetFragment.TYPE_TEXT: + intent = new Intent(this, PostTextActivity.class); + intent.putExtra(PostTextActivity.EXTRA_SUBREDDIT_NAME, subredditName); + startActivity(intent); + break; + case PostTypeBottomSheetFragment.TYPE_LINK: + intent = new Intent(this, PostLinkActivity.class); + intent.putExtra(PostLinkActivity.EXTRA_SUBREDDIT_NAME, subredditName); + startActivity(intent); + break; + case PostTypeBottomSheetFragment.TYPE_IMAGE: + intent = new Intent(this, PostImageActivity.class); + intent.putExtra(PostImageActivity.EXTRA_SUBREDDIT_NAME, subredditName); + startActivity(intent); + break; + case PostTypeBottomSheetFragment.TYPE_VIDEO: + intent = new Intent(this, PostVideoActivity.class); + intent.putExtra(PostVideoActivity.EXTRA_SUBREDDIT_NAME, subredditName); + startActivity(intent); + } + } + + public void postScrollUp() { + fab.show(); + } + + public void postScrollDown() { + fab.hide(); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + if(!getClass().getName().equals(event.excludeActivityClassName)) { + finish(); + } + } + + @Subscribe + public void onChangeNSFWEvent(ChangeNSFWEvent changeNSFWEvent) { + ((FragmentCommunicator) mFragment).changeNSFW(changeNSFWEvent.nsfw); + } + + + private static class InsertSubredditDataAsyncTask extends AsyncTask { + + interface InsertSubredditDataAsyncTaskListener { + void insertSuccess(); + } + + private SubredditDao mSubredditDao; + private SubredditData subredditData; + private InsertSubredditDataAsyncTaskListener insertSubredditDataAsyncTaskListener; + + InsertSubredditDataAsyncTask(RedditDataRoomDatabase db, SubredditData subredditData, + InsertSubredditDataAsyncTaskListener insertSubredditDataAsyncTaskListener) { + mSubredditDao = db.subredditDao(); + this.subredditData = subredditData; + this.insertSubredditDataAsyncTaskListener = insertSubredditDataAsyncTaskListener; + } + + @Override + protected Void doInBackground(final Void... params) { + mSubredditDao.insert(subredditData); + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + insertSubredditDataAsyncTaskListener.insertSuccess(); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java new file mode 100644 index 00000000..c22f0df8 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java @@ -0,0 +1,800 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.lifecycle.ViewModelProvider; +import androidx.viewpager.widget.ViewPager; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.request.RequestOptions; +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.appbar.CollapsingToolbarLayout; +import com.google.android.material.chip.Chip; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; +import com.google.android.material.snackbar.Snackbar; +import com.google.android.material.tabs.TabLayout; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import javax.inject.Inject; +import javax.inject.Named; + +import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; +import ml.docilealligator.infinityforreddit.Event.ChangeNSFWEvent; +import ml.docilealligator.infinityforreddit.AsyncTask.CheckIsFollowingUserAsyncTask; +import ml.docilealligator.infinityforreddit.Fragment.CommentsListingFragment; +import ml.docilealligator.infinityforreddit.ContentFontStyle; +import ml.docilealligator.infinityforreddit.DeleteThing; +import ml.docilealligator.infinityforreddit.FetchUserData; +import ml.docilealligator.infinityforreddit.FontStyle; +import ml.docilealligator.infinityforreddit.FragmentCommunicator; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.Fragment.PostFragment; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.ReadMessage; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserDao; +import ml.docilealligator.infinityforreddit.AsyncTask.SwitchAccountAsyncTask; +import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; +import ml.docilealligator.infinityforreddit.TitleFontStyle; +import ml.docilealligator.infinityforreddit.User.UserDao; +import ml.docilealligator.infinityforreddit.User.UserData; +import ml.docilealligator.infinityforreddit.User.UserViewModel; +import butterknife.BindView; +import butterknife.ButterKnife; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import ml.docilealligator.infinityforreddit.UserFollowing; +import ml.docilealligator.infinityforreddit.Fragment.UserThingSortTypeBottomSheetFragment; +import pl.droidsonroids.gif.GifImageView; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class ViewUserDetailActivity extends AppCompatActivity implements UserThingSortTypeBottomSheetFragment.UserThingSortTypeSelectionCallback { + + public static final String EXTRA_USER_NAME_KEY = "EUNK"; + public static final String EXTRA_MESSAGE_FULLNAME = "ENF"; + public static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; + + private static final String FETCH_USER_INFO_STATE = "FSIS"; + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + private static final String ACCOUNT_NAME_STATE = "ANS"; + private static final String IS_IN_LAZY_MODE_STATE = "IILMS"; + private static final String MESSAGE_FULLNAME_STATE = "MFS"; + private static final String NEW_ACCOUNT_NAME_STATE = "NANS"; + + @BindView(R.id.coordinator_layout_view_user_detail_activity) CoordinatorLayout coordinatorLayout; + @BindView(R.id.view_pager_view_user_detail_activity) ViewPager viewPager; + @BindView(R.id.appbar_layout_view_user_detail) AppBarLayout appBarLayout; + @BindView(R.id.tab_layout_view_user_detail_activity) TabLayout tabLayout; + @BindView(R.id.collapsing_toolbar_layout_view_user_detail_activity) CollapsingToolbarLayout collapsingToolbarLayout; + @BindView(R.id.banner_image_view_view_user_detail_activity) GifImageView bannerImageView; + @BindView(R.id.icon_gif_image_view_view_user_detail_activity) GifImageView iconGifImageView; + @BindView(R.id.user_name_text_view_view_user_detail_activity) TextView userNameTextView; + @BindView(R.id.subscribe_user_chip_view_user_detail_activity) Chip subscribeUserChip; + @BindView(R.id.karma_text_view_view_user_detail_activity) TextView karmaTextView; + + private SectionsPagerAdapter sectionsPagerAdapter; + + private SubscribedUserDao subscribedUserDao; + private RequestManager glide; + private UserViewModel userViewModel; + private Menu mMenu; + private AppBarLayout.LayoutParams params; + + private UserThingSortTypeBottomSheetFragment userThingSortTypeBottomSheetFragment; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String mAccountName; + private String username; + private boolean subscriptionReady = false; + private boolean mFetchUserInfoSuccess = false; + private boolean isInLazyMode = false; + private int expandedTabTextColor; + private int expandedTabBackgroundColor; + private int expandedTabIndicatorColor; + private int collapsedTabTextColor; + private int collapsedTabBackgroundColor; + private int collapsedTabIndicatorColor; + private boolean showToast = false; + private String mMessageFullname; + private String mNewAccountName; + + @Inject + @Named("no_oauth") + Retrofit mRetrofit; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); + + getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences + .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); + + setContentView(R.layout.activity_view_user_detail); + + ButterKnife.bind(this); + + EventBus.getDefault().register(this); + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + username = getIntent().getStringExtra(EXTRA_USER_NAME_KEY); + + if (savedInstanceState == null) { + mMessageFullname = getIntent().getStringExtra(EXTRA_MESSAGE_FULLNAME); + mNewAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); + getCurrentAccountAndInitializeViewPager(); + } else { + mFetchUserInfoSuccess = savedInstanceState.getBoolean(FETCH_USER_INFO_STATE); + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); + isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); + mMessageFullname = savedInstanceState.getString(MESSAGE_FULLNAME_STATE); + mNewAccountName = savedInstanceState.getString(NEW_ACCOUNT_NAME_STATE); + + if (!mNullAccessToken && mAccessToken == null) { + getCurrentAccountAndInitializeViewPager(); + } else { + initializeViewPager(); + } + } + + fetchUserInfo(); + + params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); + + Resources resources = getResources(); + + //Get status bar height + int statusBarHeight = 0; + int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android"); + if (resourceId > 0) { + statusBarHeight = resources.getDimensionPixelSize(resourceId); + } + + Toolbar toolbar = findViewById(R.id.toolbar); + ViewGroup.MarginLayoutParams toolbarLayoutParams = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); + toolbarLayoutParams.topMargin = statusBarHeight; + toolbar.setLayoutParams(toolbarLayoutParams); + + String title = "u/" + username; + userNameTextView.setText(title); + toolbar.setTitle(title); + + setSupportActionBar(toolbar); + + expandedTabTextColor = resources.getColor(R.color.tabLayoutWithExpandedCollapsingToolbarTextColor); + expandedTabBackgroundColor = resources.getColor(R.color.tabLayoutWithExpandedCollapsingToolbarTabBackground); + expandedTabIndicatorColor = resources.getColor(R.color.tabLayoutWithExpandedCollapsingToolbarTabIndicator); + + collapsedTabTextColor = resources.getColor(R.color.tabLayoutWithCollapsedCollapsingToolbarTextColor); + collapsedTabBackgroundColor = resources.getColor(R.color.tabLayoutWithCollapsedCollapsingToolbarTabBackground); + collapsedTabIndicatorColor = resources.getColor(R.color.tabLayoutWithCollapsedCollapsingToolbarTabIndicator); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 + && (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT + || resources.getBoolean(R.bool.isTablet))) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + + boolean lightNavBar = false; + if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + lightNavBar = true; + } + boolean finalLightNavBar = lightNavBar; + + View decorView = window.getDecorView(); + appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, State state) { + if (state == State.COLLAPSED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + tabLayout.setTabTextColors(collapsedTabTextColor, collapsedTabTextColor); + tabLayout.setSelectedTabIndicatorColor(collapsedTabIndicatorColor); + tabLayout.setBackgroundColor(collapsedTabBackgroundColor); + } else if (state == State.EXPANDED) { + if(finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + tabLayout.setTabTextColors(expandedTabTextColor, expandedTabTextColor); + tabLayout.setSelectedTabIndicatorColor(expandedTabIndicatorColor); + tabLayout.setBackgroundColor(expandedTabBackgroundColor); + } + } + }); + + showToast = true; + } else { + appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, State state) { + if (state == State.EXPANDED) { + tabLayout.setTabTextColors(expandedTabTextColor, expandedTabTextColor); + tabLayout.setSelectedTabIndicatorColor(expandedTabIndicatorColor); + tabLayout.setBackgroundColor(expandedTabBackgroundColor); + } else if (state == State.COLLAPSED) { + tabLayout.setTabTextColors(collapsedTabTextColor, collapsedTabTextColor); + tabLayout.setSelectedTabIndicatorColor(collapsedTabIndicatorColor); + tabLayout.setBackgroundColor(collapsedTabBackgroundColor); + } + } + }); + } + + subscribedUserDao = mRedditDataRoomDatabase.subscribedUserDao(); + glide = Glide.with(this); + + userViewModel = new ViewModelProvider(this, new UserViewModel.Factory(getApplication(), mRedditDataRoomDatabase, username)) + .get(UserViewModel.class); + userViewModel.getUserLiveData().observe(this, userData -> { + if (userData != null) { + if (userData.getBanner().equals("")) { + bannerImageView.setOnClickListener(view -> { + //Do nothing since the user has no banner image + }); + } else { + glide.load(userData.getBanner()).into(bannerImageView); + bannerImageView.setOnClickListener(view -> { + Intent intent = new Intent(this, ViewImageActivity.class); + intent.putExtra(ViewImageActivity.TITLE_KEY, title); + intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, userData.getBanner()); + intent.putExtra(ViewImageActivity.FILE_NAME_KEY, username + "-banner"); + startActivity(intent); + }); + } + + if (userData.getIconUrl().equals("")) { + glide.load(getDrawable(R.drawable.subreddit_default_icon)) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0))) + .into(iconGifImageView); + iconGifImageView.setOnClickListener(view -> { + //Do nothing since the user has no icon image + }); + } else { + glide.load(userData.getIconUrl()) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0))) + .error(glide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0)))) + .into(iconGifImageView); + + iconGifImageView.setOnClickListener(view -> { + Intent intent = new Intent(this, ViewImageActivity.class); + intent.putExtra(ViewImageActivity.TITLE_KEY, title); + intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, userData.getIconUrl()); + intent.putExtra(ViewImageActivity.FILE_NAME_KEY, username + "-icon"); + startActivity(intent); + }); + } + + if (userData.isCanBeFollowed()) { + subscribeUserChip.setVisibility(View.VISIBLE); + subscribeUserChip.setOnClickListener(view -> { + if(mAccessToken == null) { + Toast.makeText(ViewUserDetailActivity.this, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + if (subscriptionReady) { + subscriptionReady = false; + if (subscribeUserChip.getText().equals(resources.getString(R.string.follow))) { + UserFollowing.followUser(mOauthRetrofit, mRetrofit, mAccessToken, + username, mAccountName, subscribedUserDao, new UserFollowing.UserFollowingListener() { + @Override + public void onUserFollowingSuccess() { + subscribeUserChip.setText(R.string.unfollow); + subscribeUserChip.setChipBackgroundColor(resources.getColorStateList(R.color.colorAccent)); + showMessage(R.string.followed, false); + subscriptionReady = true; + } + + @Override + public void onUserFollowingFail() { + showMessage(R.string.follow_failed, false); + subscriptionReady = true; + } + }); + } else { + UserFollowing.unfollowUser(mOauthRetrofit, mRetrofit, mAccessToken, + username, mAccountName, subscribedUserDao, new UserFollowing.UserFollowingListener() { + @Override + public void onUserFollowingSuccess() { + subscribeUserChip.setText(R.string.follow); + subscribeUserChip.setChipBackgroundColor(resources.getColorStateList(R.color.backgroundColorPrimaryDark)); + showMessage(R.string.unfollowed, false); + subscriptionReady = true; + } + + @Override + public void onUserFollowingFail() { + showMessage(R.string.unfollow_failed, false); + subscriptionReady = true; + } + }); + } + } + }); + + new CheckIsFollowingUserAsyncTask(subscribedUserDao, username, mAccountName, new CheckIsFollowingUserAsyncTask.CheckIsFollowingUserListener() { + @Override + public void isSubscribed() { + subscribeUserChip.setText(R.string.unfollow); + subscribeUserChip.setChipBackgroundColor(resources.getColorStateList(R.color.colorAccent)); + subscriptionReady = true; + } + + @Override + public void isNotSubscribed() { + subscribeUserChip.setText(R.string.follow); + subscribeUserChip.setChipBackgroundColor(resources.getColorStateList(R.color.backgroundColorPrimaryDark)); + subscriptionReady = true; + } + }).execute(); + } else { + subscribeUserChip.setVisibility(View.GONE); + } + + String userFullName = "u/" + userData.getName(); + userNameTextView.setText(userFullName); + if (!title.equals(userFullName)) { + getSupportActionBar().setTitle(userFullName); + } + String karma = getString(R.string.karma_info, userData.getKarma()); + karmaTextView.setText(karma); + } + }); + + userThingSortTypeBottomSheetFragment = new UserThingSortTypeBottomSheetFragment(); + } + + private void getCurrentAccountAndInitializeViewPager() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(mNewAccountName != null) { + if(account == null || !account.getUsername().equals(mNewAccountName)) { + new SwitchAccountAsyncTask(mRedditDataRoomDatabase, mNewAccountName, newAccount -> { + EventBus.getDefault().post(new SwitchAccountEvent(getClass().getName())); + Toast.makeText(this, R.string.account_switched, Toast.LENGTH_SHORT).show(); + + mNewAccountName = null; + if(newAccount == null) { + mNullAccessToken = true; + } else { + mAccessToken = newAccount.getAccessToken(); + mAccountName = newAccount.getUsername(); + } + + initializeViewPager(); + }).execute(); + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + initializeViewPager(); + } + } else { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + + initializeViewPager(); + } + }).execute(); + } + + private void initializeViewPager() { + sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); + viewPager.setAdapter(sectionsPagerAdapter); + viewPager.setOffscreenPageLimit(2); + tabLayout.setupWithViewPager(viewPager); + + viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + if(isInLazyMode) { + if(viewPager.getCurrentItem() == 0) { + sectionsPagerAdapter.resumeLazyMode(); + } else { + sectionsPagerAdapter.pauseLazyMode(); + } + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + if(mAccessToken != null && mMessageFullname != null) { + ReadMessage.readMessage(mOauthRetrofit, mAccessToken, mMessageFullname, new ReadMessage.ReadMessageListener() { + @Override + public void readSuccess() { + mMessageFullname = null; + } + + @Override + public void readFailed() { + + } + }); + } + } + + private void fetchUserInfo() { + if (!mFetchUserInfoSuccess) { + FetchUserData.fetchUserData(mRetrofit, username, new FetchUserData.FetchUserDataListener() { + @Override + public void onFetchUserDataSuccess(UserData userData) { + new InsertUserDataAsyncTask(mRedditDataRoomDatabase.userDao(), userData, + () -> mFetchUserInfoSuccess = true).execute(); + } + + @Override + public void onFetchUserDataFailed() { + showMessage(R.string.cannot_fetch_user_info, true); + mFetchUserInfoSuccess = false; + } + }); + } + } + + public void deleteComment(String fullName) { + new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme) + .setTitle(R.string.delete_this_comment) + .setMessage(R.string.are_you_sure) + .setPositiveButton(R.string.delete, (dialogInterface, i) + -> DeleteThing.delete(mOauthRetrofit, fullName, mAccessToken, new DeleteThing.DeleteThingListener() { + @Override + public void deleteSuccess() { + Toast.makeText(ViewUserDetailActivity.this, R.string.delete_post_success, Toast.LENGTH_SHORT).show(); + } + + @Override + public void deleteFailed() { + Toast.makeText(ViewUserDetailActivity.this, R.string.delete_post_failed, Toast.LENGTH_SHORT).show(); + } + })) + .setNegativeButton(R.string.cancel, null) + .show(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.view_user_detail_activity, menu); + mMenu = menu; + MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_view_user_detail_activity); + if (isInLazyMode) { + lazyModeItem.setTitle(R.string.action_stop_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED); + collapsingToolbarLayout.setLayoutParams(params); + } else { + lazyModeItem.setTitle(R.string.action_start_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | + AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED); + collapsingToolbarLayout.setLayoutParams(params); + } + + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + case R.id.action_sort_view_user_detail_activity: + userThingSortTypeBottomSheetFragment.show(getSupportFragmentManager(), userThingSortTypeBottomSheetFragment.getTag()); + return true; + case R.id.action_search_view_user_detail_activity: + Intent intent = new Intent(this, SearchActivity.class); + intent.putExtra(SearchActivity.EXTRA_SUBREDDIT_NAME, username); + intent.putExtra(SearchActivity.EXTRA_SUBREDDIT_IS_USER, true); + intent.putExtra(SearchActivity.EXTRA_SEARCH_ONLY_SUBREDDITS, false); + startActivity(intent); + return true; + case R.id.action_refresh_view_user_detail_activity: + if(mMenu != null) { + mMenu.findItem(R.id.action_lazy_mode_view_user_detail_activity).setTitle(R.string.action_start_lazy_mode); + } + sectionsPagerAdapter.refresh(); + mFetchUserInfoSuccess = false; + fetchUserInfo(); + return true; + case R.id.action_lazy_mode_view_user_detail_activity: + MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_view_user_detail_activity); + if(isInLazyMode) { + isInLazyMode = false; + sectionsPagerAdapter.stopLazyMode(); + lazyModeItem.setTitle(R.string.action_start_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | + AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED); + collapsingToolbarLayout.setLayoutParams(params); + } else { + isInLazyMode = true; + if(sectionsPagerAdapter.startLazyMode()) { + lazyModeItem.setTitle(R.string.action_stop_lazy_mode); + appBarLayout.setExpanded(false); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED); + collapsingToolbarLayout.setLayoutParams(params); + } else { + isInLazyMode = false; + } + } + return true; + } + return false; + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(FETCH_USER_INFO_STATE, mFetchUserInfoSuccess); + outState.putBoolean(IS_IN_LAZY_MODE_STATE, isInLazyMode); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putString(ACCOUNT_NAME_STATE, mAccountName); + outState.putString(MESSAGE_FULLNAME_STATE, mMessageFullname); + outState.putString(NEW_ACCOUNT_NAME_STATE, mNewAccountName); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + private void showMessage(int resId, boolean retry) { + if(showToast) { + Toast.makeText(this, resId, Toast.LENGTH_SHORT).show(); + } else { + if (retry) { + Snackbar.make(coordinatorLayout, resId, Snackbar.LENGTH_SHORT).setAction(R.string.retry, + view -> fetchUserInfo()).show(); + } else { + Snackbar.make(coordinatorLayout, resId, Snackbar.LENGTH_SHORT).show(); + } + } + } + + @Override + public void userThingSortTypeSelected(String sortType) { + sectionsPagerAdapter.changeSortType(sortType); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + if(!getClass().getName().equals(event.excludeActivityClassName)) { + finish(); + } + } + + @Subscribe + public void onChangeNSFWEvent(ChangeNSFWEvent changeNSFWEvent) { + sectionsPagerAdapter.changeNSFW(changeNSFWEvent.nsfw); + } + + private static class InsertUserDataAsyncTask extends AsyncTask { + + interface InsertUserDataAsyncTaskListener { + void insertSuccess(); + } + + private UserDao userDao; + private UserData subredditData; + private InsertUserDataAsyncTaskListener insertUserDataAsyncTaskListener; + + InsertUserDataAsyncTask(UserDao userDao, UserData userData, + InsertUserDataAsyncTaskListener insertUserDataAsyncTaskListener) { + this.userDao = userDao; + this.subredditData = userData; + this.insertUserDataAsyncTaskListener = insertUserDataAsyncTaskListener; + } + + @Override + protected Void doInBackground(final Void... params) { + userDao.insert(subredditData); + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + insertUserDataAsyncTaskListener.insertSuccess(); + } + } + + private class SectionsPagerAdapter extends FragmentPagerAdapter { + private PostFragment postFragment; + private CommentsListingFragment commentsListingFragment; + + SectionsPagerAdapter(FragmentManager fm) { + super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); + } + + @NonNull + @Override + public Fragment getItem(int position) { + if (position == 0) { + PostFragment fragment = new PostFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_USER); + bundle.putString(PostFragment.EXTRA_USER_NAME, username); + bundle.putString(PostFragment.EXTRA_USER_WHERE, PostDataSource.USER_WHERE_SUBMITTED); + bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_NEW); + bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); + bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + fragment.setArguments(bundle); + return fragment; + } + CommentsListingFragment fragment = new CommentsListingFragment(); + Bundle bundle = new Bundle(); + bundle.putString(CommentsListingFragment.EXTRA_USERNAME, username); + bundle.putString(CommentsListingFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + bundle.putString(CommentsListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); + bundle.putBoolean(CommentsListingFragment.EXTRA_ARE_SAVED_COMMENTS, false); + fragment.setArguments(bundle); + return fragment; + } + + @Override + public int getCount() { + return 2; + } + + @Override + public CharSequence getPageTitle(int position) { + switch (position) { + case 0: + return "Posts"; + case 1: + return "Comments"; + } + return null; + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + Fragment fragment = (Fragment) super.instantiateItem(container, position); + switch (position) { + case 0: + postFragment = (PostFragment) fragment; + break; + case 1: + commentsListingFragment = (CommentsListingFragment) fragment; + } + return fragment; + } + + public void refresh() { + if (viewPager.getCurrentItem() == 0) { + if(postFragment != null) { + postFragment.refresh(); + } + } else { + if(commentsListingFragment != null) { + commentsListingFragment.refresh(); + } + } + } + + boolean startLazyMode() { + if(postFragment != null) { + return ((FragmentCommunicator) postFragment).startLazyMode(); + } + return false; + } + + void stopLazyMode() { + if(postFragment != null) { + ((FragmentCommunicator) postFragment).stopLazyMode(); + } + } + + void resumeLazyMode() { + if(postFragment != null) { + ((FragmentCommunicator) postFragment).resumeLazyMode(false); + } + } + + void pauseLazyMode() { + if(postFragment != null) { + ((FragmentCommunicator) postFragment).pauseLazyMode(false); + } + } + + public void changeSortType(String sortType) { + if(viewPager.getCurrentItem() == 0) { + if(postFragment != null) { + postFragment.changeSortType(sortType); + } + } else { + if(commentsListingFragment != null) { + commentsListingFragment.changeSortType(sortType); + } + } + } + + public void changeNSFW(boolean nsfw) { + if(postFragment != null) { + postFragment.changeNSFW(nsfw); + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewVideoActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewVideoActivity.java new file mode 100644 index 00000000..bbc659a2 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewVideoActivity.java @@ -0,0 +1,369 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.Manifest; +import android.animation.Animator; +import android.animation.ArgbEvaluator; +import android.animation.ValueAnimator; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.res.Configuration; +import android.graphics.PorterDuff; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.media.AudioManager; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import com.github.pwittchen.swipe.library.rx2.SimpleSwipeListener; +import com.github.pwittchen.swipe.library.rx2.Swipe; +import com.google.android.exoplayer2.ExoPlayerFactory; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.source.hls.HlsMediaSource; +import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; +import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; +import com.google.android.exoplayer2.trackselection.TrackSelection; +import com.google.android.exoplayer2.trackselection.TrackSelector; +import com.google.android.exoplayer2.ui.PlayerView; +import com.google.android.exoplayer2.upstream.DataSource; +import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory; +import com.google.android.exoplayer2.util.Util; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.R; + +public class ViewVideoActivity extends AppCompatActivity { + + private static final int PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 0; + + public static final String TITLE_KEY = "TK"; + public static final String SUBREDDIT_KEY = "SK"; + public static final String ID_KEY = "IK"; + + @BindView(R.id.relative_layout_view_video_activity) RelativeLayout relativeLayout; + @BindView(R.id.player_view_view_video_activity) PlayerView videoPlayerView; + + private Uri mVideoUri; + private SimpleExoPlayer player; + private DataSource.Factory dataSourceFactory; + + private Menu mMenu; + private Swipe swipe; + + private boolean wasPlaying; + private boolean isDownloading = false; + private float totalLengthY = 0.0f; + private float touchY = -1.0f; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_view_video); + ButterKnife.bind(this); + setVolumeControlStream(AudioManager.STREAM_MUSIC); + + ActionBar actionBar = getSupportActionBar(); + Drawable upArrow = getResources().getDrawable(R.drawable.ic_arrow_back_white_24dp); + actionBar.setHomeAsUpIndicator(upArrow); + actionBar.setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.transparentActionBarAndExoPlayerControllerColor))); + setTitle(""); + + if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || getResources().getBoolean(R.bool.isTablet)) { + //Set player controller bottom margin in order to display it above the navbar + int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android"); + LinearLayout controllerLinearLayout = findViewById(R.id.linear_layout_exo_playback_control_view); + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) controllerLinearLayout.getLayoutParams(); + params.bottomMargin = getResources().getDimensionPixelSize(resourceId); + } else { + //Set player controller right margin in order to display it above the navbar + int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android"); + LinearLayout controllerLinearLayout = findViewById(R.id.linear_layout_exo_playback_control_view); + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) controllerLinearLayout.getLayoutParams(); + params.rightMargin = getResources().getDimensionPixelSize(resourceId); + } + + Intent intent = getIntent(); + mVideoUri = intent.getData(); + + final float pxHeight = getResources().getDisplayMetrics().heightPixels; + + int activityColorFrom = getResources().getColor(android.R.color.black); + int actionBarColorFrom = getResources().getColor(R.color.transparentActionBarAndExoPlayerControllerColor); + int actionBarElementColorFrom = getResources().getColor(android.R.color.white); + int colorTo = getResources().getColor(android.R.color.transparent); + + final ValueAnimator activityColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), activityColorFrom, colorTo); + final ValueAnimator actionBarColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), actionBarColorFrom, colorTo); + final ValueAnimator actionBarElementColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), actionBarElementColorFrom, colorTo); + + activityColorAnimation.setDuration(300); // milliseconds + actionBarColorAnimation.setDuration(300); + actionBarElementColorAnimation.setDuration(300); + + activityColorAnimation.addUpdateListener(valueAnimator -> relativeLayout.setBackgroundColor((int) valueAnimator.getAnimatedValue())); + + actionBarColorAnimation.addUpdateListener(valueAnimator -> actionBar.setBackgroundDrawable(new ColorDrawable((int) valueAnimator.getAnimatedValue()))); + + actionBarElementColorAnimation.addUpdateListener(valueAnimator -> { + upArrow.setColorFilter((int) valueAnimator.getAnimatedValue(), PorterDuff.Mode.SRC_IN); + if(mMenu != null) { + Drawable drawable = mMenu.getItem(0).getIcon(); + drawable.setColorFilter((int) valueAnimator.getAnimatedValue(), PorterDuff.Mode.SRC_IN); + } + }); + + swipe = new Swipe(); + swipe.setListener(new SimpleSwipeListener() { + @Override + public void onSwipingUp(final MotionEvent event) { + float nowY = event.getY(); + float offset; + if(touchY == -1.0f) { + offset = 0.0f; + } else { + offset = nowY - touchY; + } + totalLengthY += offset; + touchY = nowY; + videoPlayerView.animate() + .y(totalLengthY) + .setDuration(0) + .start(); + } + + @Override + public boolean onSwipedUp(final MotionEvent event) { + videoPlayerView.animate() + .y(0) + .setDuration(300) + .start(); + + if(totalLengthY < -pxHeight / 8) { + videoPlayerView.animate() + .y(-pxHeight) + .setDuration(300) + .setListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animator) { + activityColorAnimation.start(); + actionBarColorAnimation.start(); + actionBarElementColorAnimation.start(); + } + + @Override + public void onAnimationEnd(Animator animator) { + finish(); + } + + @Override + public void onAnimationCancel(Animator animator) {} + + @Override + public void onAnimationRepeat(Animator animator) {} + }) + .start(); + } else { + videoPlayerView.animate() + .y(0) + .setDuration(300) + .start(); + } + + totalLengthY = 0.0f; + touchY = -1.0f; + return false; + } + + @Override + public void onSwipingDown(final MotionEvent event) { + float nowY = event.getY(); + float offset; + if(touchY == -1.0f) { + offset = 0.0f; + } else { + offset = nowY - touchY; + } + totalLengthY += offset; + touchY = nowY; + videoPlayerView.animate() + .y(totalLengthY) + .setDuration(0) + .start(); + } + + @Override + public boolean onSwipedDown(final MotionEvent event) { + if(totalLengthY > pxHeight / 8) { + videoPlayerView.animate() + .y(pxHeight) + .setDuration(300) + .setListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animator) { + activityColorAnimation.start(); + actionBarColorAnimation.start(); + actionBarElementColorAnimation.start(); + } + + @Override + public void onAnimationEnd(Animator animator) { + finish(); + } + + @Override + public void onAnimationCancel(Animator animator) {} + + @Override + public void onAnimationRepeat(Animator animator) {} + }) + .start(); + } else { + videoPlayerView.animate() + .y(0) + .setDuration(300) + .start(); + } + + totalLengthY = 0.0f; + touchY = -1.0f; + + return false; + } + }); + + videoPlayerView.setControllerVisibilityListener(visibility -> { + switch (visibility) { + case View.GONE: + getWindow().getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_IMMERSIVE); + break; + case View.VISIBLE: + getWindow().getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); + } + }); + + TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(); + TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); + player = ExoPlayerFactory.newSimpleInstance(this, trackSelector); + videoPlayerView.setPlayer(player); + // Produces DataSource instances through which media data is loaded. + dataSourceFactory = new DefaultHttpDataSourceFactory(Util.getUserAgent(this, "Infinity")); + // Prepare the player with the source. + player.prepare(new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(mVideoUri)); + + player.setRepeatMode(Player.REPEAT_MODE_ALL); + player.setPlayWhenReady(true); + wasPlaying = true; + } + + /*@Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.view_video, menu); + mMenu = menu; + return true; + }*/ + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + swipe.dispatchTouchEvent(ev); + return super.dispatchTouchEvent(ev); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + player.release(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + case R.id.action_download_view_video: + isDownloading = true; + if (Build.VERSION.SDK_INT >= 23) { + if (ContextCompat.checkSelfPermission(this, + Manifest.permission.WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + + // Permission is not granted + // No explanation needed; request the permission + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE); + } else { + // Permission has already been granted + download(); + } + } else { + download(); + } + return true; + } + + return false; + } + + @Override + protected void onStart() { + super.onStart(); + if(wasPlaying) { + player.setPlayWhenReady(true); + } + } + + @Override + protected void onStop() { + super.onStop(); + wasPlaying = player.getPlayWhenReady(); + player.setPlayWhenReady(false); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if(requestCode == PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE && grantResults.length > 0) { + if(grantResults[0] == PackageManager.PERMISSION_DENIED) { + Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show(); + } else if(grantResults[0] == PackageManager.PERMISSION_GRANTED && isDownloading) { + download(); + } + isDownloading = false; + } + } + + private void download() { + isDownloading = false; + } + + @Override + protected void onPause() { + super.onPause(); + overridePendingTransition(0, 0); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/AccountRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/AccountRecyclerViewAdapter.java new file mode 100644 index 00000000..6be837fd --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/AccountRecyclerViewAdapter.java @@ -0,0 +1,130 @@ +package ml.docilealligator.infinityforreddit.Adapter; + +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.core.content.ContextCompat; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.request.RequestOptions; + +import java.util.List; + +import ml.docilealligator.infinityforreddit.Account.Account; +import butterknife.BindView; +import butterknife.ButterKnife; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import ml.docilealligator.infinityforreddit.R; +import pl.droidsonroids.gif.GifImageView; + +public class AccountRecyclerViewAdapter extends RecyclerView.Adapter { + + public interface ItemSelectedListener { + void accountSelected(Account account); + void addAccountSelected(); + void anonymousSelected(); + void logoutSelected(); + } + + private List mAccounts; + private String mCurrentAccountName; + private Context mContext; + private RequestManager mGlide; + private ItemSelectedListener mItemSelectedListener; + + public AccountRecyclerViewAdapter(Context context, RequestManager glide, String currentAccountName, ItemSelectedListener itemSelectedListener) { + mContext = context; + mGlide = glide; + mCurrentAccountName = currentAccountName; + mItemSelectedListener = itemSelectedListener; + } + + @NonNull + @Override + public AccountViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new AccountViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_account, parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull AccountViewHolder holder, int position) { + if(mAccounts == null) { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0))) + .into(holder.profileImageGifImageView); + holder.usernameTextView.setText(R.string.add_account); + holder.itemView.setOnClickListener(view -> mItemSelectedListener.addAccountSelected()); + } else { + if(position < mAccounts.size()) { + mGlide.load(mAccounts.get(position).getProfileImageUrl()) + .error(mGlide.load(R.drawable.subreddit_default_icon)) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0))) + .into(holder.profileImageGifImageView); + holder.usernameTextView.setText(mAccounts.get(position).getUsername()); + holder.itemView.setOnClickListener(view -> { + mCurrentAccountName = mAccounts.get(position).getUsername(); + mItemSelectedListener.accountSelected(mAccounts.get(position)); + }); + } else if(position == mAccounts.size()) { + holder.profileImageGifImageView.setColorFilter(ContextCompat.getColor(mContext, R.color.primaryTextColor), android.graphics.PorterDuff.Mode.SRC_IN); + mGlide.load(R.drawable.ic_outline_add_circle_outline_24px) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0))) + .into(holder.profileImageGifImageView); + holder.usernameTextView.setText(R.string.add_account); + holder.itemView.setOnClickListener(view -> mItemSelectedListener.addAccountSelected()); + } else if(position == mAccounts.size() + 1) { + holder.profileImageGifImageView.setColorFilter(ContextCompat.getColor(mContext, R.color.primaryTextColor), android.graphics.PorterDuff.Mode.SRC_IN); + mGlide.load(R.drawable.ic_outline_public_24px) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0))) + .into(holder.profileImageGifImageView); + holder.usernameTextView.setText(R.string.anonymous_account); + holder.itemView.setOnClickListener(view -> mItemSelectedListener.anonymousSelected()); + } else { + holder.profileImageGifImageView.setColorFilter(ContextCompat.getColor(mContext, R.color.primaryTextColor), android.graphics.PorterDuff.Mode.SRC_IN); + mGlide.load(R.drawable.ic_outline_block_24px) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0))) + .into(holder.profileImageGifImageView); + holder.usernameTextView.setText(R.string.log_out); + holder.itemView.setOnClickListener(view -> mItemSelectedListener.logoutSelected()); + } + } + } + + @Override + public int getItemCount() { + if(mAccounts == null) { + return 1; + } else { + if(mCurrentAccountName == null) { + return mAccounts.size() + 1; + } else { + return mAccounts.size() + 3; + } + } + } + + @Override + public void onViewRecycled(@NonNull AccountViewHolder holder) { + mGlide.clear(holder.profileImageGifImageView); + holder.profileImageGifImageView.clearColorFilter(); + } + + public void changeAccountsDataset(List accounts) { + mAccounts = accounts; + notifyDataSetChanged(); + } + + class AccountViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.profile_image_item_account) GifImageView profileImageGifImageView; + @BindView(R.id.username_text_view_item_account) TextView usernameTextView; + + AccountViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java new file mode 100644 index 00000000..8ae2f13d --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java @@ -0,0 +1,1772 @@ +package ml.docilealligator.infinityforreddit.Adapter; + +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.graphics.ColorFilter; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; +import android.text.util.Linkify; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.RequestBuilder; +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.RequestOptions; +import com.bumptech.glide.request.target.Target; +import com.libRG.CustomTextView; +import com.santalu.aspectratioimageview.AspectRatioImageView; + +import java.util.ArrayList; +import java.util.Locale; + +import ml.docilealligator.infinityforreddit.Activity.CommentActivity; +import ml.docilealligator.infinityforreddit.Activity.FilteredThingActivity; +import ml.docilealligator.infinityforreddit.Activity.LinkResolverActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewImageActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewPostDetailActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewSubredditDetailActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewUserDetailActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewVideoActivity; +import ml.docilealligator.infinityforreddit.CommentData; +import ml.docilealligator.infinityforreddit.CustomView.AspectRatioGifImageView; +import butterknife.BindView; +import butterknife.ButterKnife; +import io.noties.markwon.AbstractMarkwonPlugin; +import io.noties.markwon.Markwon; +import io.noties.markwon.MarkwonConfiguration; +import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; +import io.noties.markwon.linkify.LinkifyPlugin; +import io.noties.markwon.urlprocessor.UrlProcessorRelativeToAbsolute; +import jp.wasabeef.glide.transformations.BlurTransformation; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import ml.docilealligator.infinityforreddit.FetchComment; +import ml.docilealligator.infinityforreddit.Fragment.ModifyCommentBottomSheetFragment; +import ml.docilealligator.infinityforreddit.AsyncTask.LoadSubredditIconAsyncTask; +import ml.docilealligator.infinityforreddit.AsyncTask.LoadUserDataAsyncTask; +import ml.docilealligator.infinityforreddit.Post; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.RedditUtils; +import ml.docilealligator.infinityforreddit.SaveThing; +import ml.docilealligator.infinityforreddit.VoteThing; +import retrofit2.Retrofit; + +import static ml.docilealligator.infinityforreddit.Activity.CommentActivity.WRITE_COMMENT_REQUEST_CODE; + +public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter { + private static final int VIEW_TYPE_POST_DETAIL = 0; + private static final int VIEW_TYPE_FIRST_LOADING = 1; + private static final int VIEW_TYPE_FIRST_LOADING_FAILED = 2; + private static final int VIEW_TYPE_NO_COMMENT_PLACEHOLDER = 3; + private static final int VIEW_TYPE_COMMENT = 4; + private static final int VIEW_TYPE_LOAD_MORE_CHILD_COMMENTS = 5; + private static final int VIEW_TYPE_IS_LOADING_MORE_COMMENTS = 6; + private static final int VIEW_TYPE_LOAD_MORE_COMMENTS_FAILED = 7; + private static final int VIEW_TYPE_VIEW_ALL_COMMENTS = 8; + + private Activity mActivity; + private Retrofit mRetrofit; + private Retrofit mOauthRetrofit; + private RedditDataRoomDatabase mRedditDataRoomDatabase; + private RequestManager mGlide; + private Markwon mMarkwon; + private String mAccessToken; + private String mAccountName; + private Post mPost; + private ArrayList mVisibleComments; + private String mSubredditNamePrefixed; + private Locale mLocale; + private String mSingleCommentId; + private boolean mIsSingleCommentThreadMode; + private boolean mNeedBlurNSFW; + private boolean mNeedBlurSpoiler; + private CommentRecyclerViewAdapterCallback mCommentRecyclerViewAdapterCallback; + private boolean isInitiallyLoading; + private boolean isInitiallyLoadingFailed; + private boolean mHasMoreComments; + private boolean loadMoreCommentsFailed; + + public interface CommentRecyclerViewAdapterCallback { + void updatePost(Post post); + void retryFetchingComments(); + void retryFetchingMoreComments(); + } + + public CommentAndPostRecyclerViewAdapter(Activity activity, Retrofit retrofit, Retrofit oauthRetrofit, + RedditDataRoomDatabase redditDataRoomDatabase, RequestManager glide, + String accessToken, String accountName, Post post, Locale locale, + String singleCommentId, boolean isSingleCommentThreadMode, + boolean needBlurNSFW, boolean needBlurSpoiler, + CommentRecyclerViewAdapterCallback commentRecyclerViewAdapterCallback) { + mActivity = activity; + mRetrofit = retrofit; + mOauthRetrofit = oauthRetrofit; + mRedditDataRoomDatabase = redditDataRoomDatabase; + mGlide = glide; + mMarkwon = Markwon.builder(mActivity) + .usePlugin(new AbstractMarkwonPlugin() { + @Override + public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { + builder.linkResolver((view, link) -> { + Intent intent = new Intent(mActivity, LinkResolverActivity.class); + Uri uri = Uri.parse(link); + if(uri.getScheme() == null && uri.getHost() == null) { + intent.setData(LinkResolverActivity.getRedditUriByPath(link)); + } else { + intent.setData(uri); + } + mActivity.startActivity(intent); + }).urlProcessor(new UrlProcessorRelativeToAbsolute("https://www.reddit.com")); + } + }) + .usePlugin(StrikethroughPlugin.create()) + .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) + .build(); + mAccessToken = accessToken; + mAccountName = accountName; + mPost = post; + mVisibleComments = new ArrayList<>(); + mSubredditNamePrefixed = post.getSubredditNamePrefixed(); + mLocale = locale; + mSingleCommentId = singleCommentId; + mIsSingleCommentThreadMode = isSingleCommentThreadMode; + mNeedBlurNSFW = needBlurNSFW; + mNeedBlurSpoiler = needBlurSpoiler; + mCommentRecyclerViewAdapterCallback = commentRecyclerViewAdapterCallback; + isInitiallyLoading = true; + isInitiallyLoadingFailed = false; + mHasMoreComments = false; + loadMoreCommentsFailed = false; + } + + @Override + public int getItemViewType(int position) { + if(position == 0) { + return VIEW_TYPE_POST_DETAIL; + } + + if(mVisibleComments.size() == 0) { + if(position == 1) { + if(isInitiallyLoading) { + return VIEW_TYPE_FIRST_LOADING; + } else if(isInitiallyLoadingFailed) { + return VIEW_TYPE_FIRST_LOADING_FAILED; + } else { + return VIEW_TYPE_NO_COMMENT_PLACEHOLDER; + } + } + } + + if(mIsSingleCommentThreadMode) { + if(position == 1) { + return VIEW_TYPE_VIEW_ALL_COMMENTS; + } + + if(position == mVisibleComments.size() + 2) { + if(mHasMoreComments) { + return VIEW_TYPE_IS_LOADING_MORE_COMMENTS; + } else { + return VIEW_TYPE_LOAD_MORE_COMMENTS_FAILED; + } + } + + CommentData comment = mVisibleComments.get(position - 2); + if(!comment.isPlaceHolder()) { + return VIEW_TYPE_COMMENT; + } else { + return VIEW_TYPE_LOAD_MORE_CHILD_COMMENTS; + } + } else { + if(position == mVisibleComments.size() + 1) { + if(mHasMoreComments) { + return VIEW_TYPE_IS_LOADING_MORE_COMMENTS; + } else { + return VIEW_TYPE_LOAD_MORE_COMMENTS_FAILED; + } + } + + CommentData comment = mVisibleComments.get(position - 1); + if(!comment.isPlaceHolder()) { + return VIEW_TYPE_COMMENT; + } else { + return VIEW_TYPE_LOAD_MORE_CHILD_COMMENTS; + } + } + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + switch (viewType) { + case VIEW_TYPE_POST_DETAIL: + return new PostDetailViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_post_detail, parent, false)); + case VIEW_TYPE_FIRST_LOADING: + return new LoadCommentsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_comments, parent, false)); + case VIEW_TYPE_FIRST_LOADING_FAILED: + return new LoadCommentsFailedViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_comments_failed_placeholder, parent, false)); + case VIEW_TYPE_NO_COMMENT_PLACEHOLDER: + return new NoCommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_no_comment_placeholder, parent, false)); + case VIEW_TYPE_COMMENT: + return new CommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment, parent, false)); + case VIEW_TYPE_LOAD_MORE_CHILD_COMMENTS: + return new LoadMoreChildCommentsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_more_comments_placeholder, parent, false)); + case VIEW_TYPE_IS_LOADING_MORE_COMMENTS: + return new IsLoadingMoreCommentsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment_footer_loading, parent, false)); + case VIEW_TYPE_LOAD_MORE_COMMENTS_FAILED: + return new LoadMoreCommentsFailedViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment_footer_error, parent, false)); + default: + return new ViewAllCommentsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view_all_comments, parent, false)); + } + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if(holder.getItemViewType() == VIEW_TYPE_POST_DETAIL) { + ((PostDetailViewHolder) holder).mTitleTextView.setText(mPost.getTitle()); + if(mPost.getSubredditNamePrefixed().startsWith("u/")) { + if(mPost.getAuthorIconUrl() == null) { + String authorName = mPost.getAuthor().equals("[deleted]") ? mPost.getSubredditNamePrefixed().substring(2) : mPost.getAuthor(); + new LoadUserDataAsyncTask(mRedditDataRoomDatabase.userDao(), authorName, mOauthRetrofit, iconImageUrl -> { + if(mActivity != null && getItemCount() > 0) { + if(iconImageUrl == null || iconImageUrl.equals("")) { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((PostDetailViewHolder) holder).mIconGifImageView); + } else { + mGlide.load(iconImageUrl) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((PostDetailViewHolder) holder).mIconGifImageView); + } + + if(holder.getAdapterPosition() >= 0) { + mPost.setAuthorIconUrl(iconImageUrl); + } + } + }).execute(); + } else if(!mPost.getAuthorIconUrl().equals("")) { + mGlide.load(mPost.getAuthorIconUrl()) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((PostDetailViewHolder) holder).mIconGifImageView); + } else { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((PostDetailViewHolder) holder).mIconGifImageView); + } + } else { + if(mPost.getSubredditIconUrl() == null) { + new LoadSubredditIconAsyncTask( + mRedditDataRoomDatabase, mPost.getSubredditNamePrefixed().substring(2), + mRetrofit, iconImageUrl -> { + if(iconImageUrl == null || iconImageUrl.equals("")) { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((PostDetailViewHolder) holder).mIconGifImageView); + } else { + mGlide.load(iconImageUrl) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((PostDetailViewHolder) holder).mIconGifImageView); + } + + mPost.setSubredditIconUrl(iconImageUrl); + }).execute(); + } else if(!mPost.getSubredditIconUrl().equals("")) { + mGlide.load(mPost.getSubredditIconUrl()) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((PostDetailViewHolder) holder).mIconGifImageView); + } else { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((PostDetailViewHolder) holder).mIconGifImageView); + } + } + + switch (mPost.getVoteType()) { + case 1: + //Upvote + ((PostDetailViewHolder) holder).mUpvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.upvoted), PorterDuff.Mode.SRC_IN); + ((PostDetailViewHolder) holder).mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.upvoted)); + break; + case -1: + //Downvote + ((PostDetailViewHolder) holder).mDownvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.downvoted), PorterDuff.Mode.SRC_IN); + ((PostDetailViewHolder) holder).mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.downvoted)); + break; + case 0: + ((PostDetailViewHolder) holder).mUpvoteButton.clearColorFilter(); + ((PostDetailViewHolder) holder).mDownvoteButton.clearColorFilter(); + ((PostDetailViewHolder) holder).mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); + } + + if(mPost.getPostType() != Post.TEXT_TYPE && mPost.getPostType() != Post.NO_PREVIEW_LINK_TYPE) { + ((PostDetailViewHolder) holder).mRelativeLayout.setVisibility(View.VISIBLE); + ((PostDetailViewHolder) holder).mImageView.setVisibility(View.VISIBLE); + ((PostDetailViewHolder) holder).mImageView.setRatio((float) mPost.getPreviewHeight() / (float) mPost.getPreviewWidth()); + loadImage((PostDetailViewHolder) holder); + } else { + ((PostDetailViewHolder) holder).mRelativeLayout.setVisibility(View.GONE); + ((PostDetailViewHolder) holder).mImageView.setVisibility(View.GONE); + } + + if(mPost.isArchived()) { + ((PostDetailViewHolder) holder).mUpvoteButton + .setColorFilter(ContextCompat.getColor(mActivity, R.color.voteAndReplyUnavailableVoteButtonColor), android.graphics.PorterDuff.Mode.SRC_IN); + ((PostDetailViewHolder) holder).mDownvoteButton + .setColorFilter(ContextCompat.getColor(mActivity, R.color.voteAndReplyUnavailableVoteButtonColor), android.graphics.PorterDuff.Mode.SRC_IN); + } + + if(mPost.isCrosspost()) { + ((PostDetailViewHolder) holder).mCrosspostImageView.setOnClickListener(view -> { + Intent crosspostIntent = new Intent(mActivity, ViewPostDetailActivity.class); + crosspostIntent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, mPost.getCrosspostParentId()); + mActivity.startActivity(crosspostIntent); + }); + ((PostDetailViewHolder) holder).mCrosspostImageView.setVisibility(View.VISIBLE); + } + + ((PostDetailViewHolder) holder).mSubredditTextView.setText(mPost.getSubredditNamePrefixed()); + ((PostDetailViewHolder) holder).mUserTextView.setText(mPost.getAuthorNamePrefixed()); + + ((PostDetailViewHolder) holder).mPostTimeTextView.setText(mPost.getPostTime()); + + if(mPost.getGilded() > 0) { + ((PostDetailViewHolder) holder).mGildedImageView.setVisibility(View.VISIBLE); + ((PostDetailViewHolder) holder).mGildedNumberTextView.setVisibility(View.VISIBLE); + String gildedNumber = mActivity.getResources().getString(R.string.gilded_count, mPost.getGilded()); + ((PostDetailViewHolder) holder).mGildedNumberTextView.setText(gildedNumber); + } + + if(mPost.isArchived()) { + ((PostDetailViewHolder) holder).mArchivedImageView.setVisibility(View.VISIBLE); + } + + if(mPost.isLocked()) { + ((PostDetailViewHolder) holder).mLockedImageView.setVisibility(View.VISIBLE); + } + + if(mPost.isSpoiler() || mPost.getFlair() != null) { + ((PostDetailViewHolder) holder).spoilerFlairlinearLayout.setVisibility(View.VISIBLE); + } + + if(mPost.isSpoiler()) { + ((PostDetailViewHolder) holder).spoilerTextView.setVisibility(View.VISIBLE); + } + + if(mPost.getFlair() != null) { + ((PostDetailViewHolder) holder).flairTextView.setVisibility(View.VISIBLE); + ((PostDetailViewHolder) holder).flairTextView.setText(mPost.getFlair()); + } + + if(mPost.isNSFW()) { + ((PostDetailViewHolder) holder).mNSFWTextView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, FilteredThingActivity.class); + intent.putExtra(FilteredThingActivity.EXTRA_NAME, mSubredditNamePrefixed.substring(2)); + intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); + intent.putExtra(FilteredThingActivity.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_HOT); + intent.putExtra(FilteredThingActivity.EXTRA_FILTER, Post.NSFW_TYPE); + mActivity.startActivity(intent); + }); + ((PostDetailViewHolder) holder).mNSFWTextView.setVisibility(View.VISIBLE); + } else { + ((PostDetailViewHolder) holder).mNSFWTextView.setVisibility(View.GONE); + } + + String scoreWithVote = Integer.toString(mPost.getScore() + mPost.getVoteType()); + ((PostDetailViewHolder) holder).mScoreTextView.setText(scoreWithVote); + + ((PostDetailViewHolder) holder).mTypeTextView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, FilteredThingActivity.class); + intent.putExtra(FilteredThingActivity.EXTRA_NAME, mSubredditNamePrefixed.substring(2)); + intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); + intent.putExtra(FilteredThingActivity.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_HOT); + intent.putExtra(FilteredThingActivity.EXTRA_FILTER, mPost.getPostType()); + mActivity.startActivity(intent); + + }); + + switch (mPost.getPostType()) { + case Post.IMAGE_TYPE: + ((PostDetailViewHolder) holder).mTypeTextView.setText("IMAGE"); + + ((PostDetailViewHolder) holder).mImageView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, ViewImageActivity.class); + intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, mPost.getUrl()); + intent.putExtra(ViewImageActivity.TITLE_KEY, mPost.getTitle()); + intent.putExtra(ViewImageActivity.FILE_NAME_KEY, mPost.getSubredditNamePrefixed().substring(2) + + "-" + mPost.getId().substring(3)); + mActivity.startActivity(intent); + }); + break; + case Post.LINK_TYPE: + ((PostDetailViewHolder) holder).mTypeTextView.setText("LINK"); + + ((PostDetailViewHolder) holder).linkTextView.setVisibility(View.VISIBLE); + String domain = Uri.parse(mPost.getUrl()).getHost(); + ((PostDetailViewHolder) holder).linkTextView.setText(domain); + + ((PostDetailViewHolder) holder).mImageView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, LinkResolverActivity.class); + Uri uri = Uri.parse(mPost.getUrl()); + if(uri.getScheme() == null && uri.getHost() == null) { + intent.setData(LinkResolverActivity.getRedditUriByPath(mPost.getUrl())); + } else { + intent.setData(uri); + } + mActivity.startActivity(intent); + }); + break; + case Post.GIF_VIDEO_TYPE: + ((PostDetailViewHolder) holder).mTypeTextView.setText("GIF"); + + final Uri gifVideoUri = Uri.parse(mPost.getVideoUrl()); + ((PostDetailViewHolder) holder).mImageView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, ViewVideoActivity.class); + intent.setData(gifVideoUri); + intent.putExtra(ViewVideoActivity.TITLE_KEY, mPost.getTitle()); + intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, mPost.getSubredditName()); + intent.putExtra(ViewVideoActivity.ID_KEY, mPost.getId()); + mActivity.startActivity(intent); + }); + break; + case Post.VIDEO_TYPE: + ((PostDetailViewHolder) holder).mTypeTextView.setText("VIDEO"); + + final Uri videoUri = Uri.parse(mPost.getVideoUrl()); + ((PostDetailViewHolder) holder).mImageView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, ViewVideoActivity.class); + intent.setData(videoUri); + intent.putExtra(ViewVideoActivity.TITLE_KEY, mPost.getTitle()); + intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, mPost.getSubredditName()); + intent.putExtra(ViewVideoActivity.ID_KEY, mPost.getId()); + mActivity.startActivity(intent); + }); + break; + case Post.NO_PREVIEW_LINK_TYPE: + ((PostDetailViewHolder) holder).mTypeTextView.setText("LINK"); + + ((PostDetailViewHolder) holder).linkTextView.setVisibility(View.VISIBLE); + String noPreviewLinkDomain = Uri.parse(mPost.getUrl()).getHost(); + ((PostDetailViewHolder) holder).linkTextView.setText(noPreviewLinkDomain); + + if(mPost.getSelfText() != null && !mPost.getSelfText().equals("")) { + ((PostDetailViewHolder) holder).mContentMarkdownView.setVisibility(View.VISIBLE); + mMarkwon.setMarkdown(((PostDetailViewHolder) holder).mContentMarkdownView, mPost.getSelfText()); + } + + ((PostDetailViewHolder) holder).mNoPreviewLinkImageView.setVisibility(View.VISIBLE); + ((PostDetailViewHolder) holder).mNoPreviewLinkImageView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, LinkResolverActivity.class); + Uri uri = Uri.parse(mPost.getUrl()); + if(uri.getScheme() == null && uri.getHost() == null) { + intent.setData(LinkResolverActivity.getRedditUriByPath(mPost.getUrl())); + } else { + intent.setData(uri); + } + mActivity.startActivity(intent); + }); + break; + case Post.TEXT_TYPE: + ((PostDetailViewHolder) holder).mTypeTextView.setText("TEXT"); + + if(!mPost.getSelfText().equals("")) { + ((PostDetailViewHolder) holder).mContentMarkdownView.setVisibility(View.VISIBLE); + mMarkwon.setMarkdown(((PostDetailViewHolder) holder).mContentMarkdownView, mPost.getSelfText()); + } + break; + } + + ((PostDetailViewHolder) holder).commentButton.setOnClickListener(view -> { + if(mAccessToken == null) { + Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + Intent intent = new Intent(mActivity, CommentActivity.class); + intent.putExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY, mPost.getFullName()); + intent.putExtra(CommentActivity.EXTRA_COMMENT_PARENT_TEXT_KEY, mPost.getTitle()); + intent.putExtra(CommentActivity.EXTRA_IS_REPLYING_KEY, false); + intent.putExtra(CommentActivity.EXTRA_PARENT_DEPTH_KEY, 0); + mActivity.startActivityForResult(intent, WRITE_COMMENT_REQUEST_CODE); + }); + + ((PostDetailViewHolder) holder).commentsCountTextView.setText(Integer.toString(mPost.getnComments())); + + if(mPost.isSaved()) { + ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); + } else { + ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); + } + + ((PostDetailViewHolder) holder).saveButton.setOnClickListener(view -> { + if(mAccessToken == null) { + Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + if(mPost.isSaved()) { + ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); + SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, mPost.getFullName(), + new SaveThing.SaveThingListener() { + @Override + public void success() { + mPost.setSaved(false); + ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); + Toast.makeText(mActivity, R.string.post_unsaved_success, Toast.LENGTH_SHORT).show(); + mCommentRecyclerViewAdapterCallback.updatePost(mPost); + } + + @Override + public void failed() { + mPost.setSaved(true); + ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); + Toast.makeText(mActivity, R.string.post_unsaved_failed, Toast.LENGTH_SHORT).show(); + mCommentRecyclerViewAdapterCallback.updatePost(mPost); + } + }); + } else { + ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); + SaveThing.saveThing(mOauthRetrofit, mAccessToken, mPost.getFullName(), + new SaveThing.SaveThingListener() { + @Override + public void success() { + mPost.setSaved(true); + ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); + Toast.makeText(mActivity, R.string.post_saved_success, Toast.LENGTH_SHORT).show(); + mCommentRecyclerViewAdapterCallback.updatePost(mPost); + } + + @Override + public void failed() { + mPost.setSaved(false); + ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); + Toast.makeText(mActivity, R.string.post_saved_failed, Toast.LENGTH_SHORT).show(); + mCommentRecyclerViewAdapterCallback.updatePost(mPost); + } + }); + } + }); + } else if(holder.getItemViewType() == VIEW_TYPE_COMMENT) { + CommentData comment; + if(mIsSingleCommentThreadMode) { + comment = mVisibleComments.get(holder.getAdapterPosition() - 2); + } else { + comment = mVisibleComments.get(holder.getAdapterPosition() - 1); + } + + if(mIsSingleCommentThreadMode && comment.getId().equals(mSingleCommentId)) { + ((CommentViewHolder) holder).itemView.setBackgroundColor( + mActivity.getResources().getColor(R.color.singleCommentThreadBackgroundColor)); + } + + String authorPrefixed = "u/" + comment.getAuthor(); + ((CommentViewHolder) holder).authorTextView.setText(authorPrefixed); + + if(comment.isSubmitter()) { + ((CommentViewHolder) holder).authorTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.submitter)); + ((CommentViewHolder) holder).authorTypeImageView.setVisibility(View.VISIBLE); + ((CommentViewHolder) holder).authorTypeImageView. + setColorFilter(ContextCompat.getColor(mActivity, R.color.submitter), android.graphics.PorterDuff.Mode.SRC_IN); + ((CommentViewHolder) holder).authorTypeImageView.setImageResource(R.drawable.ic_mic_14dp); + } else if(comment.isModerator()) { + ((CommentViewHolder) holder).authorTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.moderator)); + ((CommentViewHolder) holder).authorTypeImageView.setVisibility(View.VISIBLE); + ((CommentViewHolder) holder).authorTypeImageView. + setColorFilter(ContextCompat.getColor(mActivity, R.color.moderator), android.graphics.PorterDuff.Mode.SRC_IN); + ((CommentViewHolder) holder).authorTypeImageView.setImageResource(R.drawable.ic_verified_user_14dp); + } + + ((CommentViewHolder) holder).commentTimeTextView.setText(comment.getCommentTime()); + + mMarkwon.setMarkdown(((CommentViewHolder) holder).commentMarkdownView, comment.getCommentContent()); + ((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType())); + + ((CommentViewHolder) holder).itemView.setPadding(comment.getDepth() * 16, 0, 0, 0); + if(comment.getDepth() > 0) { + switch (comment.getDepth() % 7) { + case 0: + ((CommentViewHolder) holder).verticalBlock + .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar7)); + break; + case 1: + ((CommentViewHolder) holder).verticalBlock + .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar1)); + break; + case 2: + ((CommentViewHolder) holder).verticalBlock + .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar2)); + break; + case 3: + ((CommentViewHolder) holder).verticalBlock + .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar3)); + break; + case 4: + ((CommentViewHolder) holder).verticalBlock + .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar4)); + break; + case 5: + ((CommentViewHolder) holder).verticalBlock + .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar5)); + break; + case 6: + ((CommentViewHolder) holder).verticalBlock + .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar6)); + break; + } + ViewGroup.LayoutParams params = ((CommentViewHolder) holder).verticalBlock.getLayoutParams(); + params.width = 16; + ((CommentViewHolder) holder).verticalBlock.setLayoutParams(params); + } + + if(!mPost.isArchived() && !mPost.isLocked() && comment.getAuthor().equals(mAccountName)) { + ((CommentViewHolder) holder).moreButton.setVisibility(View.VISIBLE); + + ((CommentViewHolder) holder).moreButton.setOnClickListener(view -> { + ModifyCommentBottomSheetFragment modifyCommentBottomSheetFragment = new ModifyCommentBottomSheetFragment(); + Bundle bundle = new Bundle(); + bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_COMMENT_CONTENT, comment.getCommentContent()); + bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_COMMENT_FULLNAME, comment.getFullName()); + if(mIsSingleCommentThreadMode) { + bundle.putInt(ModifyCommentBottomSheetFragment.EXTRA_POSITION, holder.getAdapterPosition() - 2); + } else { + bundle.putInt(ModifyCommentBottomSheetFragment.EXTRA_POSITION, holder.getAdapterPosition() - 1); + } + modifyCommentBottomSheetFragment.setArguments(bundle); + modifyCommentBottomSheetFragment.show(((AppCompatActivity) mActivity).getSupportFragmentManager(), modifyCommentBottomSheetFragment.getTag()); + }); + } + + if (comment.hasReply()) { + if(comment.isExpanded()) { + ((CommentViewHolder) holder).expandButton.setImageResource(R.drawable.ic_expand_less_black_20dp); + } else { + ((CommentViewHolder) holder).expandButton.setImageResource(R.drawable.ic_expand_more_black_20dp); + } + ((CommentViewHolder) holder).expandButton.setVisibility(View.VISIBLE); + } + + switch (comment.getVoteType()) { + case CommentData.VOTE_TYPE_UPVOTE: + ((CommentViewHolder) holder).upVoteButton + .setColorFilter(ContextCompat.getColor(mActivity, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.upvoted)); + break; + case CommentData.VOTE_TYPE_DOWNVOTE: + ((CommentViewHolder) holder).downVoteButton + .setColorFilter(ContextCompat.getColor(mActivity, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.downvoted)); + break; + } + + if(mPost.isArchived()) { + ((CommentViewHolder) holder).replyButton + .setColorFilter(ContextCompat.getColor(mActivity, R.color.voteAndReplyUnavailableVoteButtonColor), + android.graphics.PorterDuff.Mode.SRC_IN); + ((CommentViewHolder) holder).upVoteButton + .setColorFilter(ContextCompat.getColor(mActivity, R.color.voteAndReplyUnavailableVoteButtonColor), + android.graphics.PorterDuff.Mode.SRC_IN); + ((CommentViewHolder) holder).downVoteButton + .setColorFilter(ContextCompat.getColor(mActivity, R.color.voteAndReplyUnavailableVoteButtonColor), + android.graphics.PorterDuff.Mode.SRC_IN); + } + + if(mPost.isLocked()) { + ((CommentViewHolder) holder).replyButton + .setColorFilter(ContextCompat.getColor(mActivity, R.color.voteAndReplyUnavailableVoteButtonColor), + android.graphics.PorterDuff.Mode.SRC_IN); + } + + ((CommentViewHolder) holder).replyButton.setOnClickListener(view -> { + if(mAccessToken == null) { + Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + if(mPost.isArchived()) { + Toast.makeText(mActivity, R.string.archived_post_reply_unavailable, Toast.LENGTH_SHORT).show(); + return; + } + + if(mPost.isLocked()) { + Toast.makeText(mActivity, R.string.locked_post_reply_unavailable, Toast.LENGTH_SHORT).show(); + return; + } + + Intent intent = new Intent(mActivity, CommentActivity.class); + intent.putExtra(CommentActivity.EXTRA_PARENT_DEPTH_KEY, comment.getDepth() + 1); + intent.putExtra(CommentActivity.EXTRA_COMMENT_PARENT_TEXT_KEY, comment.getCommentContent()); + intent.putExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY, comment.getFullName()); + intent.putExtra(CommentActivity.EXTRA_IS_REPLYING_KEY, true); + + int parentPosition = mIsSingleCommentThreadMode ? holder.getAdapterPosition() - 2 : holder.getAdapterPosition() - 1; + intent.putExtra(CommentActivity.EXTRA_PARENT_POSITION_KEY, parentPosition); + mActivity.startActivityForResult(intent, CommentActivity.WRITE_COMMENT_REQUEST_CODE); + }); + + ((CommentViewHolder) holder).upVoteButton.setOnClickListener(view -> { + if(mPost.isArchived()) { + Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); + return; + } + + if(mAccessToken == null) { + Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + int commentPosition = mIsSingleCommentThreadMode ? holder.getAdapterPosition() - 2 : holder.getAdapterPosition() - 1; + + int previousVoteType = mVisibleComments.get(commentPosition).getVoteType(); + String newVoteType; + + ((CommentViewHolder) holder).downVoteButton.clearColorFilter(); + + if(previousVoteType != CommentData.VOTE_TYPE_UPVOTE) { + //Not upvoted before + mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_UPVOTE); + newVoteType = RedditUtils.DIR_UPVOTE; + ((CommentViewHolder) holder).upVoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.upvoted)); + } else { + //Upvoted before + mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_NO_VOTE); + newVoteType = RedditUtils.DIR_UNVOTE; + ((CommentViewHolder) holder).upVoteButton.clearColorFilter(); + ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); + } + + ((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(mVisibleComments.get(commentPosition).getScore() + mVisibleComments.get(commentPosition).getVoteType())); + + VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { + @Override + public void onVoteThingSuccess(int position) { + if(newVoteType.equals(RedditUtils.DIR_UPVOTE)) { + mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_UPVOTE); + ((CommentViewHolder) holder).upVoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.upvoted)); + } else { + mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_NO_VOTE); + ((CommentViewHolder) holder).upVoteButton.clearColorFilter(); + ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); + } + + ((CommentViewHolder) holder).downVoteButton.clearColorFilter(); + ((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(mVisibleComments.get(commentPosition).getScore() + mVisibleComments.get(commentPosition).getVoteType())); + } + + @Override + public void onVoteThingFail(int position) { } + }, mVisibleComments.get(commentPosition).getFullName(), newVoteType, holder.getAdapterPosition()); + }); + + ((CommentViewHolder) holder).downVoteButton.setOnClickListener(view -> { + if(mPost.isArchived()) { + Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); + return; + } + + if(mAccessToken == null) { + Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + int commentPosition = mIsSingleCommentThreadMode ? holder.getAdapterPosition() - 2 : holder.getAdapterPosition() - 1; + + int previousVoteType = mVisibleComments.get(commentPosition).getVoteType(); + String newVoteType; + + ((CommentViewHolder) holder).upVoteButton.clearColorFilter(); + + if(previousVoteType != CommentData.VOTE_TYPE_DOWNVOTE) { + //Not downvoted before + mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_DOWNVOTE); + newVoteType = RedditUtils.DIR_DOWNVOTE; + ((CommentViewHolder) holder).downVoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.downvoted)); + } else { + //Downvoted before + mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_NO_VOTE); + newVoteType = RedditUtils.DIR_UNVOTE; + ((CommentViewHolder) holder).downVoteButton.clearColorFilter(); + ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); + } + + ((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(mVisibleComments.get(commentPosition).getScore() + mVisibleComments.get(commentPosition).getVoteType())); + + VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { + @Override + public void onVoteThingSuccess(int position1) { + if(newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) { + mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_DOWNVOTE); + ((CommentViewHolder) holder).downVoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.downvoted)); + } else { + mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_NO_VOTE); + ((CommentViewHolder) holder).downVoteButton.clearColorFilter(); + ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); + } + + ((CommentViewHolder) holder).upVoteButton.clearColorFilter(); + ((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(mVisibleComments.get(commentPosition).getScore() + mVisibleComments.get(commentPosition).getVoteType())); + } + + @Override + public void onVoteThingFail(int position1) { } + }, mVisibleComments.get(commentPosition).getFullName(), newVoteType, holder.getAdapterPosition()); + }); + + if(comment.isSaved()) { + ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_20dp); + } else { + ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_20dp); + } + + ((CommentViewHolder) holder).saveButton.setOnClickListener(view -> { + if (comment.isSaved()) { + comment.setSaved(false); + SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, comment.getFullName(), new SaveThing.SaveThingListener() { + @Override + public void success() { + comment.setSaved(false); + ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_20dp); + Toast.makeText(mActivity, R.string.comment_unsaved_success, Toast.LENGTH_SHORT).show(); + } + + @Override + public void failed() { + comment.setSaved(true); + ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_20dp); + Toast.makeText(mActivity, R.string.comment_unsaved_failed, Toast.LENGTH_SHORT).show(); + } + }); + } else { + comment.setSaved(true); + SaveThing.saveThing(mOauthRetrofit, mAccessToken, comment.getFullName(), new SaveThing.SaveThingListener() { + @Override + public void success() { + comment.setSaved(true); + ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_20dp); + Toast.makeText(mActivity, R.string.comment_saved_success, Toast.LENGTH_SHORT).show(); + } + + @Override + public void failed() { + comment.setSaved(false); + ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_20dp); + Toast.makeText(mActivity, R.string.comment_saved_failed, Toast.LENGTH_SHORT).show(); + } + }); + } + }); + } else if(holder instanceof LoadMoreChildCommentsViewHolder) { + CommentData placeholder; + placeholder = mIsSingleCommentThreadMode ? mVisibleComments.get(holder.getAdapterPosition() - 2) + : mVisibleComments.get(holder.getAdapterPosition() - 1); + + ((LoadMoreChildCommentsViewHolder) holder).itemView.setPadding(placeholder.getDepth() * 16, 0, 0, 0); + if(placeholder.getDepth() > 0) { + switch (placeholder.getDepth() % 7) { + case 0: + ((LoadMoreChildCommentsViewHolder) holder).verticalBlock + .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar7)); + break; + case 1: + ((LoadMoreChildCommentsViewHolder) holder).verticalBlock + .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar1)); + break; + case 2: + ((LoadMoreChildCommentsViewHolder) holder).verticalBlock + .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar2)); + break; + case 3: + ((LoadMoreChildCommentsViewHolder) holder).verticalBlock + .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar3)); + break; + case 4: + ((LoadMoreChildCommentsViewHolder) holder).verticalBlock + .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar4)); + break; + case 5: + ((LoadMoreChildCommentsViewHolder) holder).verticalBlock + .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar5)); + break; + case 6: + ((LoadMoreChildCommentsViewHolder) holder).verticalBlock + .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar6)); + break; + } + + ViewGroup.LayoutParams params = ((LoadMoreChildCommentsViewHolder) holder).verticalBlock.getLayoutParams(); + params.width = 16; + ((LoadMoreChildCommentsViewHolder) holder).verticalBlock.setLayoutParams(params); + } + + if(placeholder.isLoadingMoreChildren()) { + ((LoadMoreChildCommentsViewHolder) holder).placeholderTextView.setText(R.string.loading); + } else if(placeholder.isLoadMoreChildrenFailed()) { + ((LoadMoreChildCommentsViewHolder) holder).placeholderTextView.setText(R.string.comment_load_more_comments_failed); + } else { + ((LoadMoreChildCommentsViewHolder) holder).placeholderTextView.setText(R.string.comment_load_more_comments); + } + } else if(holder instanceof LoadMoreCommentsFailedViewHolder) { + ((LoadMoreCommentsFailedViewHolder) holder).errorTextView.setText(R.string.load_comments_failed); + } + } + + private void loadImage(PostDetailViewHolder holder) { + RequestBuilder imageRequestBuilder = mGlide.load(mPost.getPreviewUrl()) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + holder.mLoadImageProgressBar.setVisibility(View.GONE); + holder.mLoadImageErrorTextView.setVisibility(View.VISIBLE); + holder.mLoadImageErrorTextView.setOnClickListener(view -> { + holder.mLoadImageProgressBar.setVisibility(View.VISIBLE); + holder.mLoadImageErrorTextView.setVisibility(View.GONE); + loadImage(holder); + }); + return false; + } + + @Override + public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + holder.mLoadWrapper.setVisibility(View.GONE); + return false; + } + }); + + if((mPost.isNSFW() && mNeedBlurNSFW) || (mPost.isSpoiler() && mNeedBlurSpoiler)) { + imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 2))) + .into(holder.mImageView); + } else { + imageRequestBuilder.into(holder.mImageView); + } + } + + public void updatePost(Post post) { + mPost = post; + notifyItemChanged(0); + } + + private int getParentPosition(int position) { + if(position >= mVisibleComments.size()) { + return -1; + } + + int childDepth = mVisibleComments.get(position).getDepth(); + for(int i = position; i >= 0; i--) { + if(mVisibleComments.get(i).getDepth() < childDepth) { + return i; + } + } + return -1; + } + + private void expandChildren(int position) { + CommentData comment = mVisibleComments.get(position); + if(!comment.isExpanded()) { + comment.setExpanded(true); + ArrayList children = comment.getChildren(); + if(children != null && children.size() > 0) { + for(int i = 0; i < children.size(); i++) { + children.get(i).setExpanded(false); + } + mVisibleComments.addAll(position + 1, children); + if(mIsSingleCommentThreadMode) { + notifyItemRangeInserted(position + 3, children.size()); + } else { + notifyItemRangeInserted(position + 2, children.size()); + } + } + } + } + + private void collapseChildren(int position) { + mVisibleComments.get(position).setExpanded(false); + int depth = mVisibleComments.get(position).getDepth(); + int allChildrenSize = 0; + for(int i = position + 1; i < mVisibleComments.size(); i++) { + if(mVisibleComments.get(i).getDepth() > depth) { + allChildrenSize++; + } else { + break; + } + } + + mVisibleComments.subList(position + 1, position + 1 + allChildrenSize).clear(); + if(mIsSingleCommentThreadMode) { + notifyItemRangeRemoved(position + 3, allChildrenSize); + } else { + notifyItemRangeRemoved(position + 2, allChildrenSize); + } + } + + public void addComments(ArrayList comments, boolean hasMoreComments) { + if(mVisibleComments.size() == 0) { + isInitiallyLoading = false; + isInitiallyLoadingFailed = false; + if(comments.size() == 0) { + notifyItemChanged(1); + } else { + notifyItemRemoved(1); + } + } + + int sizeBefore = mVisibleComments.size(); + mVisibleComments.addAll(comments); + if(mIsSingleCommentThreadMode) { + notifyItemRangeInserted(sizeBefore + 2, comments.size()); + } else { + notifyItemRangeInserted(sizeBefore + 1, comments.size()); + } + + if(mHasMoreComments != hasMoreComments) { + if(hasMoreComments) { + if(mIsSingleCommentThreadMode) { + notifyItemInserted(mVisibleComments.size() + 2); + } else { + notifyItemInserted(mVisibleComments.size() + 1); + } + } else { + if(mIsSingleCommentThreadMode) { + notifyItemRemoved(mVisibleComments.size() + 2); + } else { + notifyItemRemoved(mVisibleComments.size() + 1); + } + } + } + mHasMoreComments = hasMoreComments; + } + + public void addComment(CommentData comment) { + if(mVisibleComments.size() == 0 || isInitiallyLoadingFailed) { + notifyItemRemoved(1); + } + + mVisibleComments.add(0, comment); + + if(isInitiallyLoading) { + notifyItemInserted(2); + } else { + notifyItemInserted(1); + } + } + + public void addChildComment(CommentData comment, String parentFullname, int parentPosition) { + if(!parentFullname.equals(mVisibleComments.get(parentPosition).getFullName())) { + for(int i = 0; i < mVisibleComments.size(); i++) { + if(parentFullname.equals(mVisibleComments.get(i).getFullName())) { + parentPosition = i; + break; + } + } + } + + mVisibleComments.get(parentPosition).addChild(comment); + mVisibleComments.get(parentPosition).setHasReply(true); + if(!mVisibleComments.get(parentPosition).isExpanded()) { + expandChildren(parentPosition); + if(mIsSingleCommentThreadMode) { + notifyItemChanged(parentPosition + 2); + } else { + notifyItemChanged(parentPosition + 1); + } + } else { + mVisibleComments.add(parentPosition + 1, comment); + if(mIsSingleCommentThreadMode) { + notifyItemInserted(parentPosition + 3); + } else { + notifyItemInserted(parentPosition + 2); + } + } + } + + public void setSingleComment(String singleCommentId, boolean isSingleCommentThreadMode) { + mSingleCommentId = singleCommentId; + mIsSingleCommentThreadMode = isSingleCommentThreadMode; + } + + public ArrayList getVisibleComments() { + return mVisibleComments; + } + + public void initiallyLoading() { + if(mVisibleComments.size() != 0) { + int previousSize = mVisibleComments.size(); + mVisibleComments.clear(); + if(mIsSingleCommentThreadMode) { + notifyItemRangeRemoved(1, previousSize + 1); + } else { + notifyItemRangeRemoved(1, previousSize); + } + } + + if(isInitiallyLoading || isInitiallyLoadingFailed || mVisibleComments.size() == 0) { + isInitiallyLoading = true; + isInitiallyLoadingFailed = false; + notifyItemChanged(1); + } else { + isInitiallyLoading = true; + isInitiallyLoadingFailed = false; + notifyItemInserted(1); + } + } + + public void initiallyLoadCommentsFailed() { + isInitiallyLoading = false; + isInitiallyLoadingFailed = true; + notifyItemChanged(1); + } + + public void loadMoreCommentsFailed() { + loadMoreCommentsFailed = true; + if(mIsSingleCommentThreadMode) { + notifyItemChanged(mVisibleComments.size() + 2); + } else { + notifyItemChanged(mVisibleComments.size() + 1); + } + } + + public void editComment(String commentContent, int position) { + mVisibleComments.get(position).setCommentContent(commentContent); + if(mIsSingleCommentThreadMode) { + notifyItemChanged(position + 2); + } else { + notifyItemChanged(position + 1); + } + } + + public void deleteComment(int position) { + if(mVisibleComments.get(position).hasReply()) { + mVisibleComments.get(position).setAuthor("[deleted]"); + mVisibleComments.get(position).setCommentContent("[deleted]"); + if(mIsSingleCommentThreadMode) { + notifyItemChanged(position + 2); + } else { + notifyItemChanged(position + 1); + } + } else { + mVisibleComments.remove(position); + if(mIsSingleCommentThreadMode) { + notifyItemRemoved(position + 2); + } else { + notifyItemRemoved(position + 1); + } + } + } + + public void setBlurNSFW(boolean needBlurNSFW) { + mNeedBlurNSFW = needBlurNSFW; + } + + public void setBlurSpoiler(boolean needBlurSpoiler) { + mNeedBlurSpoiler = needBlurSpoiler; + } + + @Override + public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { + if (holder instanceof CommentViewHolder) { + ((CommentViewHolder) holder).authorTextView.setTextColor( + ContextCompat.getColor(mActivity, R.color.colorPrimaryDarkDayNightTheme)); + mGlide.clear(((CommentViewHolder) holder).authorTypeImageView); + ((CommentViewHolder) holder).authorTypeImageView.setVisibility(View.GONE); + ((CommentViewHolder) holder).moreButton.setVisibility(View.GONE); + ((CommentViewHolder) holder).expandButton.setVisibility(View.GONE); + ((CommentViewHolder) holder).upVoteButton.clearColorFilter(); + ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); + ((CommentViewHolder) holder).downVoteButton.clearColorFilter(); + ((CommentViewHolder) holder).replyButton.clearColorFilter(); + ViewGroup.LayoutParams params = ((CommentViewHolder) holder).verticalBlock.getLayoutParams(); + params.width = 0; + ((CommentViewHolder) holder).verticalBlock.setLayoutParams(params); + ((CommentViewHolder) holder).itemView.setPadding(0, 0, 0, 0); + ((CommentViewHolder) holder).itemView.setBackgroundColor( + mActivity.getResources().getColor(R.color.cardViewBackgroundColor)); + } else if(holder instanceof PostDetailViewHolder) { + ((PostDetailViewHolder) holder).mUpvoteButton.clearColorFilter(); + ((PostDetailViewHolder) holder).mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); + ((PostDetailViewHolder) holder).mDownvoteButton.clearColorFilter(); + ((PostDetailViewHolder) holder).spoilerFlairlinearLayout.setVisibility(View.GONE); + ((PostDetailViewHolder) holder).flairTextView.setVisibility(View.GONE); + ((PostDetailViewHolder) holder).spoilerTextView.setVisibility(View.GONE); + ((PostDetailViewHolder) holder).mNSFWTextView.setVisibility(View.GONE); + } else if(holder instanceof LoadMoreChildCommentsViewHolder) { + ((LoadMoreChildCommentsViewHolder) holder).itemView.setPadding(0, 0, 0, 0); + ViewGroup.LayoutParams params = ((LoadMoreChildCommentsViewHolder) holder).verticalBlock.getLayoutParams(); + params.width = 0; + ((LoadMoreChildCommentsViewHolder) holder).verticalBlock.setLayoutParams(params); + } + } + + @Override + public int getItemCount() { + if(isInitiallyLoading || isInitiallyLoadingFailed || mVisibleComments.size() == 0) { + return 2; + } + + if(mHasMoreComments || loadMoreCommentsFailed) { + if(mIsSingleCommentThreadMode) { + return mVisibleComments.size() + 3; + } else { + return mVisibleComments.size() + 2; + } + } + + if(mIsSingleCommentThreadMode) { + return mVisibleComments.size() + 2; + } else { + return mVisibleComments.size() + 1; + } + } + + class PostDetailViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.icon_gif_image_view_item_post_detail) AspectRatioGifImageView mIconGifImageView; + @BindView(R.id.subreddit_text_view_item_post_detail) TextView mSubredditTextView; + @BindView(R.id.user_text_view_item_post_detail) TextView mUserTextView; + @BindView(R.id.post_time_text_view_item_post_detail) TextView mPostTimeTextView; + @BindView(R.id.title_text_view_item_post_detail) TextView mTitleTextView; + @BindView(R.id.content_markdown_view_item_post_detail) TextView mContentMarkdownView; + @BindView(R.id.type_text_view_item_post_detail) CustomTextView mTypeTextView; + @BindView(R.id.gilded_image_view_item_post_detail) ImageView mGildedImageView; + @BindView(R.id.gilded_number_text_view_item_post_detail) TextView mGildedNumberTextView; + @BindView(R.id.crosspost_image_view_item_post_detail) ImageView mCrosspostImageView; + @BindView(R.id.archived_image_view_item_post_detail) ImageView mArchivedImageView; + @BindView(R.id.locked_image_view_item_post_detail) ImageView mLockedImageView; + @BindView(R.id.nsfw_text_view_item_post_detail) CustomTextView mNSFWTextView; + @BindView(R.id.spoiler_flair_linear_layout_item_post_detail) LinearLayout spoilerFlairlinearLayout; + @BindView(R.id.spoiler_custom_text_view_item_post_detail) CustomTextView spoilerTextView; + @BindView(R.id.flair_custom_text_view_item_post_detail) CustomTextView flairTextView; + @BindView(R.id.link_text_view_item_post_detail) TextView linkTextView; + @BindView(R.id.image_view_wrapper_item_post_detail) RelativeLayout mRelativeLayout; + @BindView(R.id.load_wrapper_item_post_detail) RelativeLayout mLoadWrapper; + @BindView(R.id.progress_bar_item_post_detail) ProgressBar mLoadImageProgressBar; + @BindView(R.id.load_image_error_text_view_item_post_detail) TextView mLoadImageErrorTextView; + @BindView(R.id.image_view_item_post_detail) AspectRatioImageView mImageView; + @BindView(R.id.image_view_no_preview_link_item_post_detail) ImageView mNoPreviewLinkImageView; + @BindView(R.id.plus_button_item_post_detail) ImageView mUpvoteButton; + @BindView(R.id.score_text_view_item_post_detail) TextView mScoreTextView; + @BindView(R.id.minus_button_item_post_detail) ImageView mDownvoteButton; + @BindView(R.id.comment_button_item_post_detail) ImageView commentButton; + @BindView(R.id.comments_count_item_post_detail) TextView commentsCountTextView; + @BindView(R.id.save_button_item_post_detail) ImageView saveButton; + @BindView(R.id.share_button_item_post_detail) ImageView mShareButton; + + PostDetailViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + + mIconGifImageView.setOnClickListener(view -> mSubredditTextView.performClick()); + + mSubredditTextView.setOnClickListener(view -> { + Intent intent; + if(mPost.getSubredditNamePrefixed().equals("u/" + mPost.getAuthor())) { + intent = new Intent(mActivity, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mPost.getAuthor()); + } else { + intent = new Intent(mActivity, ViewSubredditDetailActivity.class); + intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, + mPost.getSubredditNamePrefixed().substring(2)); + } + mActivity.startActivity(intent); + }); + + mUserTextView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mPost.getAuthor()); + mActivity.startActivity(intent); + }); + + mShareButton.setOnClickListener(view -> { + try { + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("text/plain"); + String extraText = mPost.getTitle() + "\n" + mPost.getPermalink(); + intent.putExtra(Intent.EXTRA_TEXT, extraText); + mActivity.startActivity(Intent.createChooser(intent, mActivity.getString(R.string.share))); + } catch (ActivityNotFoundException e) { + Toast.makeText(mActivity, R.string.no_activity_found_for_share, Toast.LENGTH_SHORT).show(); + } + }); + + mUpvoteButton.setOnClickListener(view -> { + if(mPost.isArchived()) { + Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); + return; + } + + if(mAccessToken == null) { + Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + ColorFilter previousUpvoteButtonColorFilter = mUpvoteButton.getColorFilter(); + ColorFilter previousDownvoteButtonColorFilter = mDownvoteButton.getColorFilter(); + int previousScoreTextViewColor = mScoreTextView.getCurrentTextColor(); + + int previousVoteType = mPost.getVoteType(); + String newVoteType; + + mDownvoteButton.clearColorFilter(); + + if(previousUpvoteButtonColorFilter == null) { + //Not upvoted before + mPost.setVoteType(1); + newVoteType = RedditUtils.DIR_UPVOTE; + mUpvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); + mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.upvoted)); + } else { + //Upvoted before + mPost.setVoteType(0); + newVoteType = RedditUtils.DIR_UNVOTE; + mUpvoteButton.clearColorFilter(); + mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); + } + + mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType())); + + mCommentRecyclerViewAdapterCallback.updatePost(mPost); + + VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingWithoutPositionListener() { + @Override + public void onVoteThingSuccess() { + if(newVoteType.equals(RedditUtils.DIR_UPVOTE)) { + mPost.setVoteType(1); + mUpvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); + mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.upvoted)); + } else { + mPost.setVoteType(0); + mUpvoteButton.clearColorFilter(); + mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); + } + + mDownvoteButton.clearColorFilter(); + mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType())); + + mCommentRecyclerViewAdapterCallback.updatePost(mPost); + } + + @Override + public void onVoteThingFail() { + Toast.makeText(mActivity, R.string.vote_failed, Toast.LENGTH_SHORT).show(); + mPost.setVoteType(previousVoteType); + mScoreTextView.setText(Integer.toString(mPost.getScore() + previousVoteType)); + mUpvoteButton.setColorFilter(previousUpvoteButtonColorFilter); + mDownvoteButton.setColorFilter(previousDownvoteButtonColorFilter); + mScoreTextView.setTextColor(previousScoreTextViewColor); + + mCommentRecyclerViewAdapterCallback.updatePost(mPost); + } + }, mPost.getFullName(), newVoteType); + }); + + mDownvoteButton.setOnClickListener(view -> { + if(mPost.isArchived()) { + Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); + return; + } + + if(mAccessToken == null) { + Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + ColorFilter previousUpvoteButtonColorFilter = mUpvoteButton.getColorFilter(); + ColorFilter previousDownvoteButtonColorFilter = mDownvoteButton.getColorFilter(); + int previousScoreTextViewColor = mScoreTextView.getCurrentTextColor(); + + int previousVoteType = mPost.getVoteType(); + String newVoteType; + + mUpvoteButton.clearColorFilter(); + + if(previousDownvoteButtonColorFilter == null) { + //Not upvoted before + mPost.setVoteType(-1); + newVoteType = RedditUtils.DIR_DOWNVOTE; + mDownvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); + mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.downvoted)); + } else { + //Upvoted before + mPost.setVoteType(0); + newVoteType = RedditUtils.DIR_UNVOTE; + mDownvoteButton.clearColorFilter(); + mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); + } + + mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType())); + + mCommentRecyclerViewAdapterCallback.updatePost(mPost); + + VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingWithoutPositionListener() { + @Override + public void onVoteThingSuccess() { + if(newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) { + mPost.setVoteType(-1); + mDownvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); + mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.downvoted)); + } else { + mPost.setVoteType(0); + mDownvoteButton.clearColorFilter(); + mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); + } + + mUpvoteButton.clearColorFilter(); + mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType())); + + mCommentRecyclerViewAdapterCallback.updatePost(mPost); + } + + @Override + public void onVoteThingFail() { + Toast.makeText(mActivity, R.string.vote_failed, Toast.LENGTH_SHORT).show(); + mPost.setVoteType(previousVoteType); + mScoreTextView.setText(Integer.toString(mPost.getScore() + previousVoteType)); + mUpvoteButton.setColorFilter(previousUpvoteButtonColorFilter); + mDownvoteButton.setColorFilter(previousDownvoteButtonColorFilter); + mScoreTextView.setTextColor(previousScoreTextViewColor); + + mCommentRecyclerViewAdapterCallback.updatePost(mPost); + } + }, mPost.getFullName(), newVoteType); + }); + } + } + + class CommentViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.author_text_view_item_post_comment) TextView authorTextView; + @BindView(R.id.author_type_image_view_item_comment) ImageView authorTypeImageView; + @BindView(R.id.comment_time_text_view_item_post_comment) TextView commentTimeTextView; + @BindView(R.id.comment_markdown_view_item_post_comment) TextView commentMarkdownView; + @BindView(R.id.up_vote_button_item_post_comment) ImageView upVoteButton; + @BindView(R.id.score_text_view_item_post_comment) TextView scoreTextView; + @BindView(R.id.down_vote_button_item_post_comment) ImageView downVoteButton; + @BindView(R.id.more_button_item_post_comment) ImageView moreButton; + @BindView(R.id.save_button_item_post_comment) ImageView saveButton; + @BindView(R.id.expand_button_item_post_comment) ImageView expandButton; + @BindView(R.id.share_button_item_post_comment) ImageView shareButton; + @BindView(R.id.reply_button_item_post_comment) ImageView replyButton; + @BindView(R.id.vertical_block_item_post_comment) View verticalBlock; + + CommentViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + + authorTextView.setOnClickListener(view -> { + Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); + if(mIsSingleCommentThreadMode) { + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mVisibleComments.get(getAdapterPosition() - 2).getAuthor()); + } else { + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mVisibleComments.get(getAdapterPosition() - 1).getAuthor()); + } + mActivity.startActivity(intent); + }); + + shareButton.setOnClickListener(view -> { + try { + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("text/plain"); + String extraText = mIsSingleCommentThreadMode ? mVisibleComments.get(getAdapterPosition() - 2).getPermalink() + : mVisibleComments.get(getAdapterPosition() - 1).getPermalink(); + intent.putExtra(Intent.EXTRA_TEXT, extraText); + mActivity.startActivity(Intent.createChooser(intent, mActivity.getString(R.string.share))); + } catch (ActivityNotFoundException e) { + Toast.makeText(mActivity, R.string.no_activity_found_for_share, Toast.LENGTH_SHORT).show(); + } + }); + + expandButton.setOnClickListener(view -> { + if(expandButton.getVisibility() == View.VISIBLE) { + int commentPosition = mIsSingleCommentThreadMode ? getAdapterPosition() - 2 : getAdapterPosition() - 1; + if(mVisibleComments.get(commentPosition).isExpanded()) { + collapseChildren(commentPosition); + expandButton.setImageResource(R.drawable.ic_expand_more_black_20dp); + } else { + expandChildren(commentPosition); + mVisibleComments.get(commentPosition).setExpanded(true); + expandButton.setImageResource(R.drawable.ic_expand_less_black_20dp); + } + } + }); + + commentMarkdownView.setOnLongClickListener(view -> { + expandButton.performClick(); + return true; + }); + + itemView.setOnLongClickListener(view -> { + expandButton.performClick(); + return true; + }); + } + } + + class LoadMoreChildCommentsViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.vertical_block_item_load_more_comments) View verticalBlock; + @BindView(R.id.placeholder_text_view_item_load_more_comments) TextView placeholderTextView; + + LoadMoreChildCommentsViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + + placeholderTextView.setOnClickListener(view -> { + int commentPosition = mIsSingleCommentThreadMode ? getAdapterPosition() - 2 : getAdapterPosition() - 1; + int parentPosition = getParentPosition(commentPosition); + CommentData parentComment = mVisibleComments.get(parentPosition); + + mVisibleComments.get(commentPosition).setLoadingMoreChildren(true); + mVisibleComments.get(commentPosition).setLoadMoreChildrenFailed(false); + placeholderTextView.setText(R.string.loading); + + Retrofit retrofit = mAccessToken == null ? mRetrofit : mOauthRetrofit; + FetchComment.fetchMoreComment(retrofit, mAccessToken, parentComment.getMoreChildrenFullnames(), + parentComment.getMoreChildrenStartingIndex(), parentComment.getDepth() + 1, mLocale, + new FetchComment.FetchMoreCommentListener() { + @Override + public void onFetchMoreCommentSuccess(ArrayList expandedComments, + int childrenStartingIndex) { + if(mVisibleComments.size() > parentPosition + && parentComment.getFullName().equals(mVisibleComments.get(parentPosition).getFullName())) { + if(mVisibleComments.get(parentPosition).isExpanded()) { + if(mVisibleComments.get(parentPosition).getChildren().size() > childrenStartingIndex) { + mVisibleComments.get(parentPosition).setMoreChildrenStartingIndex(childrenStartingIndex); + mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1) + .setLoadingMoreChildren(false); + mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1) + .setLoadMoreChildrenFailed(false); + + int placeholderPosition = commentPosition; + if(mVisibleComments.get(commentPosition).getFullName().equals(parentComment.getFullName())) { + for(int i = parentPosition + 1; i < mVisibleComments.size(); i++) { + if(mVisibleComments.get(i).getFullName().equals(parentComment.getFullName())) { + placeholderPosition = i; + break; + } + } + } + + mVisibleComments.get(placeholderPosition).setLoadingMoreChildren(false); + mVisibleComments.get(placeholderPosition).setLoadMoreChildrenFailed(false); + placeholderTextView.setText(R.string.comment_load_more_comments); + + mVisibleComments.addAll(placeholderPosition, expandedComments); + if(mIsSingleCommentThreadMode) { + notifyItemRangeInserted(placeholderPosition + 2, expandedComments.size()); + } else { + notifyItemRangeInserted(placeholderPosition + 1, expandedComments.size()); + } + } else { + mVisibleComments.get(parentPosition).getChildren() + .remove(mVisibleComments.get(parentPosition).getChildren().size() - 1); + mVisibleComments.get(parentPosition).removeMoreChildrenFullnames(); + + int placeholderPosition = commentPosition; + if(mVisibleComments.get(commentPosition).getFullName().equals(parentComment.getFullName())) { + for(int i = parentPosition + 1; i < mVisibleComments.size(); i++) { + if(mVisibleComments.get(i).getFullName().equals(parentComment.getFullName())) { + placeholderPosition = i; + break; + } + } + } + + mVisibleComments.remove(placeholderPosition); + if(mIsSingleCommentThreadMode) { + notifyItemRemoved(placeholderPosition + 2); + } else { + notifyItemRemoved(placeholderPosition + 1); + } + + mVisibleComments.addAll(placeholderPosition, expandedComments); + if(mIsSingleCommentThreadMode) { + notifyItemRangeInserted(placeholderPosition + 2, expandedComments.size()); + } else { + notifyItemRangeInserted(placeholderPosition + 1, expandedComments.size()); + } + } + } else { + if(mVisibleComments.get(parentPosition).hasReply() && mVisibleComments.get(parentPosition).getChildren().size() <= childrenStartingIndex) { + mVisibleComments.get(parentPosition).getChildren() + .remove(mVisibleComments.get(parentPosition).getChildren().size() - 1); + mVisibleComments.get(parentPosition).removeMoreChildrenFullnames(); + } + } + + mVisibleComments.get(parentPosition).addChildren(expandedComments); + } else { + for(int i = 0; i < mVisibleComments.size(); i++) { + if(mVisibleComments.get(i).getFullName().equals(parentComment.getFullName())) { + if(mVisibleComments.get(i).isExpanded()) { + int placeholderPosition = i + mVisibleComments.get(i).getChildren().size(); + + if(!mVisibleComments.get(i).getFullName() + .equals(mVisibleComments.get(placeholderPosition).getFullName())) { + for(int j = i + 1; j < mVisibleComments.size(); j++) { + if(mVisibleComments.get(j).getFullName().equals(mVisibleComments.get(i).getFullName())) { + placeholderPosition = j; + } + } + } + + mVisibleComments.get(placeholderPosition).setLoadingMoreChildren(false); + mVisibleComments.get(placeholderPosition).setLoadMoreChildrenFailed(false); + placeholderTextView.setText(R.string.comment_load_more_comments); + + mVisibleComments.addAll(placeholderPosition, expandedComments); + if(mIsSingleCommentThreadMode) { + notifyItemRangeInserted(placeholderPosition + 2, expandedComments.size()); + } else { + notifyItemRangeInserted(placeholderPosition + 1, expandedComments.size()); + } + } + + mVisibleComments.get(i).getChildren().get(mVisibleComments.get(i).getChildren().size() - 1) + .setLoadingMoreChildren(false); + mVisibleComments.get(i).getChildren().get(mVisibleComments.get(i).getChildren().size() - 1) + .setLoadMoreChildrenFailed(false); + mVisibleComments.get(i).addChildren(expandedComments); + + break; + } + } + } + } + + @Override + public void onFetchMoreCommentFailed() { + if(parentPosition < mVisibleComments.size() + && parentComment.getFullName().equals(mVisibleComments.get(parentPosition).getFullName())) { + if(mVisibleComments.get(parentPosition).isExpanded()) { + int commentPosition = mIsSingleCommentThreadMode ? getAdapterPosition() - 2 : getAdapterPosition() - 1; + int placeholderPosition = commentPosition; + if(commentPosition >= mVisibleComments.size() || !mVisibleComments.get(commentPosition).getFullName().equals(parentComment.getFullName())) { + for(int i = parentPosition + 1; i < mVisibleComments.size(); i++) { + if(mVisibleComments.get(i).getFullName().equals(parentComment.getFullName())) { + placeholderPosition = i; + break; + } + } + } + + mVisibleComments.get(placeholderPosition).setLoadingMoreChildren(false); + mVisibleComments.get(placeholderPosition).setLoadMoreChildrenFailed(true); + placeholderTextView.setText(R.string.comment_load_more_comments_failed); + } + + mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1) + .setLoadingMoreChildren(false); + mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1) + .setLoadMoreChildrenFailed(true); + } else { + for(int i = 0; i < mVisibleComments.size(); i++) { + if(mVisibleComments.get(i).getFullName().equals(parentComment.getFullName())) { + if(mVisibleComments.get(i).isExpanded()) { + int placeholderPosition = i + mVisibleComments.get(i).getChildren().size(); + if(!mVisibleComments.get(placeholderPosition).getFullName().equals(mVisibleComments.get(i).getFullName())) { + for(int j = i + 1; j < mVisibleComments.size(); j++) { + if(mVisibleComments.get(j).getFullName().equals(mVisibleComments.get(i).getFullName())) { + placeholderPosition = j; + break; + } + } + } + + mVisibleComments.get(placeholderPosition).setLoadingMoreChildren(false); + mVisibleComments.get(placeholderPosition).setLoadMoreChildrenFailed(true); + placeholderTextView.setText(R.string.comment_load_more_comments_failed); + } + + mVisibleComments.get(i).getChildren().get(mVisibleComments.get(i).getChildren().size() - 1).setLoadingMoreChildren(false); + mVisibleComments.get(i).getChildren().get(mVisibleComments.get(i).getChildren().size() - 1).setLoadMoreChildrenFailed(true); + + break; + } + } + } + } + }); + }); + } + } + + class LoadCommentsViewHolder extends RecyclerView.ViewHolder { + LoadCommentsViewHolder(@NonNull View itemView) { + super(itemView); + } + } + + class LoadCommentsFailedViewHolder extends RecyclerView.ViewHolder { + LoadCommentsFailedViewHolder(@NonNull View itemView) { + super(itemView); + itemView.setOnClickListener(view -> { + mCommentRecyclerViewAdapterCallback.retryFetchingComments(); + }); + } + } + + class NoCommentViewHolder extends RecyclerView.ViewHolder { + NoCommentViewHolder(@NonNull View itemView) { + super(itemView); + } + } + + class IsLoadingMoreCommentsViewHolder extends RecyclerView.ViewHolder { + IsLoadingMoreCommentsViewHolder(@NonNull View itemView) { + super(itemView); + } + } + + class LoadMoreCommentsFailedViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.error_text_view_item_comment_footer_error) TextView errorTextView; + @BindView(R.id.retry_button_item_comment_footer_error) Button retryButton; + + LoadMoreCommentsFailedViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + + retryButton.setOnClickListener(view -> mCommentRecyclerViewAdapterCallback.retryFetchingMoreComments()); + } + } + + class ViewAllCommentsViewHolder extends RecyclerView.ViewHolder { + + ViewAllCommentsViewHolder(@NonNull View itemView) { + super(itemView); + + itemView.setOnClickListener(view -> { + if(mActivity != null && mActivity instanceof ViewPostDetailActivity) { + mIsSingleCommentThreadMode = false; + mSingleCommentId = null; + ((ViewPostDetailActivity) mActivity).changeToSingleThreadMode(); + } + }); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentsListingRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentsListingRecyclerViewAdapter.java new file mode 100644 index 00000000..884cd9ca --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentsListingRecyclerViewAdapter.java @@ -0,0 +1,438 @@ +package ml.docilealligator.infinityforreddit.Adapter; + +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.text.util.Linkify; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.content.ContextCompat; +import androidx.paging.PagedListAdapter; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.RecyclerView; + +import butterknife.BindView; +import butterknife.ButterKnife; +import io.noties.markwon.AbstractMarkwonPlugin; +import io.noties.markwon.Markwon; +import io.noties.markwon.MarkwonConfiguration; +import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; +import io.noties.markwon.linkify.LinkifyPlugin; +import ml.docilealligator.infinityforreddit.Activity.LinkResolverActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewPostDetailActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewSubredditDetailActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewUserDetailActivity; +import ml.docilealligator.infinityforreddit.CommentData; +import ml.docilealligator.infinityforreddit.Fragment.ModifyCommentBottomSheetFragment; +import ml.docilealligator.infinityforreddit.NetworkState; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditUtils; +import ml.docilealligator.infinityforreddit.SaveThing; +import ml.docilealligator.infinityforreddit.VoteThing; +import retrofit2.Retrofit; + +public class CommentsListingRecyclerViewAdapter extends PagedListAdapter { + private Context mContext; + private Retrofit mOauthRetrofit; + private Markwon mMarkwon; + private String mAccessToken; + private String mAccountName; + private int mTextColorPrimaryDark; + private int mColorAccent; + + private static final int VIEW_TYPE_DATA = 0; + private static final int VIEW_TYPE_ERROR = 1; + private static final int VIEW_TYPE_LOADING = 2; + + private NetworkState networkState; + private RetryLoadingMoreCallback mRetryLoadingMoreCallback; + + public interface RetryLoadingMoreCallback { + void retryLoadingMore(); + } + + public CommentsListingRecyclerViewAdapter(Context context, Retrofit oauthRetrofit, + String accessToken, String accountName, + RetryLoadingMoreCallback retryLoadingMoreCallback) { + super(DIFF_CALLBACK); + mContext = context; + mOauthRetrofit = oauthRetrofit; + mMarkwon = Markwon.builder(mContext) + .usePlugin(new AbstractMarkwonPlugin() { + @Override + public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { + builder.linkResolver((view, link) -> { + Intent intent = new Intent(mContext, LinkResolverActivity.class); + Uri uri = Uri.parse(link); + if(uri.getScheme() == null && uri.getHost() == null) { + intent.setData(LinkResolverActivity.getRedditUriByPath(link)); + } else { + intent.setData(uri); + } + mContext.startActivity(intent); + }); + } + }) + .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) + .usePlugin(StrikethroughPlugin.create()) + .build(); + mAccessToken = accessToken; + mAccountName = accountName; + mRetryLoadingMoreCallback = retryLoadingMoreCallback; + mTextColorPrimaryDark = mContext.getResources().getColor(R.color.colorPrimaryDarkDayNightTheme); + mColorAccent = mContext.getResources().getColor(R.color.colorAccent); + } + + private static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() { + @Override + public boolean areItemsTheSame(@NonNull CommentData commentData, @NonNull CommentData t1) { + return commentData.getId().equals(t1.getId()); + } + + @Override + public boolean areContentsTheSame(@NonNull CommentData commentData, @NonNull CommentData t1) { + return commentData.getCommentContent().equals(t1.getCommentContent()); + } + }; + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + if(viewType == VIEW_TYPE_DATA) { + return new DataViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment, parent, false)); + } else if(viewType == VIEW_TYPE_ERROR) { + return new ErrorViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_error, parent, false)); + } else { + return new LoadingViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_loading, parent, false)); + } + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if(holder instanceof DataViewHolder) { + CommentData comment = getItem(holder.getAdapterPosition()); + if(comment != null) { + if(comment.getSubredditName().substring(2).equals(comment.getLinkAuthor())) { + ((DataViewHolder) holder).authorTextView.setText("u/" + comment.getLinkAuthor()); + ((DataViewHolder) holder).authorTextView.setTextColor(mTextColorPrimaryDark); + ((DataViewHolder) holder).authorTextView.setOnClickListener(view -> { + Intent intent = new Intent(mContext, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, comment.getLinkAuthor()); + mContext.startActivity(intent); + }); + } else { + ((DataViewHolder) holder).authorTextView.setText("r/" + comment.getSubredditName()); + ((DataViewHolder) holder).authorTextView.setTextColor(mColorAccent); + ((DataViewHolder) holder).authorTextView.setOnClickListener(view -> { + Intent intent = new Intent(mContext, ViewSubredditDetailActivity.class); + intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, comment.getSubredditName()); + mContext.startActivity(intent); + }); + } + + ((DataViewHolder) holder).commentTimeTextView.setText(comment.getCommentTime()); + + mMarkwon.setMarkdown(((DataViewHolder) holder).commentMarkdownView, comment.getCommentContent()); + + ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType())); + + switch (comment.getVoteType()) { + case CommentData.VOTE_TYPE_UPVOTE: + ((DataViewHolder) holder).upvoteButton + .setColorFilter(ContextCompat.getColor(mContext, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.upvoted)); + break; + case CommentData.VOTE_TYPE_DOWNVOTE: + ((DataViewHolder) holder).downvoteButton + .setColorFilter(ContextCompat.getColor(mContext, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.downvoted)); + break; + } + + if(comment.getAuthor().equals(mAccountName)) { + ((DataViewHolder) holder).moreButton.setVisibility(View.VISIBLE); + ((DataViewHolder) holder).moreButton.setOnClickListener(view -> { + ModifyCommentBottomSheetFragment modifyCommentBottomSheetFragment = new ModifyCommentBottomSheetFragment(); + Bundle bundle = new Bundle(); + bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_COMMENT_CONTENT, comment.getCommentContent()); + bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_COMMENT_FULLNAME, comment.getFullName()); + bundle.putInt(ModifyCommentBottomSheetFragment.EXTRA_POSITION, holder.getAdapterPosition() - 1); + modifyCommentBottomSheetFragment.setArguments(bundle); + modifyCommentBottomSheetFragment.show(((AppCompatActivity) mContext).getSupportFragmentManager(), modifyCommentBottomSheetFragment.getTag()); + }); + } + + ((DataViewHolder) holder).linearLayout.setOnClickListener(view -> { + Intent intent = new Intent(mContext, ViewPostDetailActivity.class); + intent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, comment.getLinkId()); + intent.putExtra(ViewPostDetailActivity.EXTRA_SINGLE_COMMENT_ID, comment.getId()); + mContext.startActivity(intent); + }); + + ((DataViewHolder) holder).verticalBlock.setVisibility(View.GONE); + + ((DataViewHolder) holder).commentMarkdownView.setOnClickListener(view -> + ((DataViewHolder) holder).linearLayout.callOnClick()); + + ((DataViewHolder) holder).shareButton.setOnClickListener(view -> { + try { + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("text/plain"); + String extraText = comment.getPermalink(); + intent.putExtra(Intent.EXTRA_TEXT, extraText); + mContext.startActivity(Intent.createChooser(intent, mContext.getString(R.string.share))); + } catch (ActivityNotFoundException e) { + Toast.makeText(mContext, R.string.no_activity_found_for_share, Toast.LENGTH_SHORT).show(); + } + }); + + ((DataViewHolder) holder).replyButton.setVisibility(View.GONE); + + ((DataViewHolder) holder).upvoteButton.setOnClickListener(view -> { + if(mAccessToken == null) { + Toast.makeText(mContext, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + int previousVoteType = comment.getVoteType(); + String newVoteType; + + ((DataViewHolder) holder).downvoteButton.clearColorFilter(); + + if(previousVoteType != CommentData.VOTE_TYPE_UPVOTE) { + //Not upvoted before + comment.setVoteType(CommentData.VOTE_TYPE_UPVOTE); + newVoteType = RedditUtils.DIR_UPVOTE; + ((DataViewHolder) holder).upvoteButton + .setColorFilter(ContextCompat.getColor(mContext, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.upvoted)); + } else { + //Upvoted before + comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); + newVoteType = RedditUtils.DIR_UNVOTE; + ((DataViewHolder) holder).upvoteButton.clearColorFilter(); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); + } + + ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType())); + + VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { + @Override + public void onVoteThingSuccess(int position) { + if(newVoteType.equals(RedditUtils.DIR_UPVOTE)) { + comment.setVoteType(CommentData.VOTE_TYPE_UPVOTE); + ((DataViewHolder) holder).upvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.upvoted)); + } else { + comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); + ((DataViewHolder) holder).upvoteButton.clearColorFilter(); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); + } + + ((DataViewHolder) holder).downvoteButton.clearColorFilter(); + ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType())); + } + + @Override + public void onVoteThingFail(int position) { } + }, comment.getFullName(), newVoteType, holder.getAdapterPosition()); + }); + + ((DataViewHolder) holder).downvoteButton.setOnClickListener(view -> { + if(mAccessToken == null) { + Toast.makeText(mContext, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + int previousVoteType = comment.getVoteType(); + String newVoteType; + + ((DataViewHolder) holder).upvoteButton.clearColorFilter(); + + if(previousVoteType != CommentData.VOTE_TYPE_DOWNVOTE) { + //Not downvoted before + comment.setVoteType(CommentData.VOTE_TYPE_DOWNVOTE); + newVoteType = RedditUtils.DIR_DOWNVOTE; + ((DataViewHolder) holder).downvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.downvoted)); + } else { + //Downvoted before + comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); + newVoteType = RedditUtils.DIR_UNVOTE; + ((DataViewHolder) holder).downvoteButton.clearColorFilter(); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); + } + + ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType())); + + VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { + @Override + public void onVoteThingSuccess(int position1) { + if(newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) { + comment.setVoteType(CommentData.VOTE_TYPE_DOWNVOTE); + ((DataViewHolder) holder).downvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.downvoted)); + } else { + comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); + ((DataViewHolder) holder).downvoteButton.clearColorFilter(); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); + } + + ((DataViewHolder) holder).upvoteButton.clearColorFilter(); + ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType())); + } + + @Override + public void onVoteThingFail(int position1) { } + }, comment.getFullName(), newVoteType, holder.getAdapterPosition()); + }); + + if(comment.isSaved()) { + ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_20dp); + } else { + ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_20dp); + } + + ((DataViewHolder) holder).saveButton.setOnClickListener(view -> { + if (comment.isSaved()) { + comment.setSaved(false); + SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, comment.getFullName(), new SaveThing.SaveThingListener() { + @Override + public void success() { + comment.setSaved(false); + ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_20dp); + Toast.makeText(mContext, R.string.comment_unsaved_success, Toast.LENGTH_SHORT).show(); + } + + @Override + public void failed() { + comment.setSaved(true); + ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_20dp); + Toast.makeText(mContext, R.string.comment_unsaved_failed, Toast.LENGTH_SHORT).show(); + } + }); + } else { + comment.setSaved(true); + SaveThing.saveThing(mOauthRetrofit, mAccessToken, comment.getFullName(), new SaveThing.SaveThingListener() { + @Override + public void success() { + comment.setSaved(true); + ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_20dp); + Toast.makeText(mContext, R.string.comment_saved_success, Toast.LENGTH_SHORT).show(); + } + + @Override + public void failed() { + comment.setSaved(false); + ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_20dp); + Toast.makeText(mContext, R.string.comment_saved_failed, Toast.LENGTH_SHORT).show(); + } + }); + } + }); + } + } + } + + @Override + public int getItemViewType(int position) { + // Reached at the end + if (hasExtraRow() && position == getItemCount() - 1) { + if (networkState.getStatus() == NetworkState.Status.LOADING) { + return VIEW_TYPE_LOADING; + } else { + return VIEW_TYPE_ERROR; + } + } else { + return VIEW_TYPE_DATA; + } + } + + @Override + public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { + if(holder instanceof DataViewHolder) { + ((DataViewHolder) holder).upvoteButton.clearColorFilter(); + ((DataViewHolder) holder).downvoteButton.clearColorFilter(); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); + } + } + + @Override + public int getItemCount() { + if(hasExtraRow()) { + return super.getItemCount() + 1; + } + return super.getItemCount(); + } + + private boolean hasExtraRow() { + return networkState != null && networkState.getStatus() != NetworkState.Status.SUCCESS; + } + + public void setNetworkState(NetworkState newNetworkState) { + NetworkState previousState = this.networkState; + boolean previousExtraRow = hasExtraRow(); + this.networkState = newNetworkState; + boolean newExtraRow = hasExtraRow(); + if (previousExtraRow != newExtraRow) { + if (previousExtraRow) { + notifyItemRemoved(super.getItemCount()); + } else { + notifyItemInserted(super.getItemCount()); + } + } else if (newExtraRow && !previousState.equals(newNetworkState)) { + notifyItemChanged(getItemCount() - 1); + } + } + + class DataViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.linear_layout_item_comment) LinearLayout linearLayout; + @BindView(R.id.vertical_block_item_post_comment) View verticalBlock; + @BindView(R.id.author_text_view_item_post_comment) TextView authorTextView; + @BindView(R.id.comment_time_text_view_item_post_comment) TextView commentTimeTextView; + @BindView(R.id.comment_markdown_view_item_post_comment) TextView commentMarkdownView; + @BindView(R.id.up_vote_button_item_post_comment) ImageView upvoteButton; + @BindView(R.id.score_text_view_item_post_comment) TextView scoreTextView; + @BindView(R.id.down_vote_button_item_post_comment) ImageView downvoteButton; + @BindView(R.id.more_button_item_post_comment) ImageView moreButton; + @BindView(R.id.save_button_item_post_comment) ImageView saveButton; + @BindView(R.id.share_button_item_post_comment) ImageView shareButton; + @BindView(R.id.reply_button_item_post_comment) ImageView replyButton; + + DataViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + } + + class ErrorViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.error_text_view_item_footer_error) TextView errorTextView; + @BindView(R.id.retry_button_item_footer_error) Button retryButton; + + ErrorViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + errorTextView.setText(R.string.load_comments_failed); + retryButton.setOnClickListener(view -> mRetryLoadingMoreCallback.retryLoadingMore()); + } + } + + class LoadingViewHolder extends RecyclerView.ViewHolder { + LoadingViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/FlairBottomSheetRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/FlairBottomSheetRecyclerViewAdapter.java new file mode 100644 index 00000000..c7045138 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/FlairBottomSheetRecyclerViewAdapter.java @@ -0,0 +1,107 @@ +package ml.docilealligator.infinityforreddit.Adapter; + +import android.app.Activity; +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.dialog.MaterialAlertDialogBuilder; + +import java.util.ArrayList; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.Flair; +import ml.docilealligator.infinityforreddit.R; + +public class FlairBottomSheetRecyclerViewAdapter extends RecyclerView.Adapter { + public interface ItemClickListener { + void onClick(Flair flair); + } + + private Context context; + private ArrayList flairs; + private ItemClickListener itemClickListener; + + public FlairBottomSheetRecyclerViewAdapter(Context context, ItemClickListener itemClickListener) { + this.context = context; + this.itemClickListener = itemClickListener; + } + + @NonNull + @Override + public FlairViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new FlairViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_flair, null, false)); + } + + @Override + public void onBindViewHolder(@NonNull FlairViewHolder holder, int position) { + if(flairs.get(holder.getAdapterPosition()).isEditable()) { + holder.editFlairImageView.setVisibility(View.VISIBLE); + holder.editFlairImageView.setOnClickListener(view -> { + View dialogView = ((Activity) context).getLayoutInflater().inflate(R.layout.dialog_edit_flair, null); + EditText flairEditText = dialogView.findViewById(R.id.flair_edit_text_edit_flair_dialog); + flairEditText.requestFocus(); + InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); + if(imm != null) { + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + } + new MaterialAlertDialogBuilder(context, R.style.MaterialAlertDialogTheme) + .setTitle(R.string.edit_flair) + .setView(dialogView) + .setPositiveButton(R.string.ok, (dialogInterface, i) + -> { + Flair flair = flairs.get(holder.getAdapterPosition()); + flair.setText(flairEditText.getText().toString()); + itemClickListener.onClick(flair); + }) + .setNegativeButton(R.string.cancel, null) + .show(); + }); + } + + if(flairs.get(holder.getAdapterPosition()).isEditable() && flairs.get(holder.getAdapterPosition()).getText().equals("")) { + holder.itemView.setOnClickListener(view -> holder.editFlairImageView.performClick()); + } else { + holder.itemView.setOnClickListener(view -> itemClickListener.onClick(flairs.get(holder.getAdapterPosition()))); + } + + holder.flairTextView.setText(flairs.get(holder.getAdapterPosition()).getText()); + } + + @Override + public int getItemCount() { + return flairs == null ? 0 : flairs.size(); + } + + @Override + public void onViewRecycled(@NonNull FlairViewHolder holder) { + super.onViewRecycled(holder); + holder.editFlairImageView.setVisibility(View.GONE); + } + + public void changeDataset(ArrayList flairs) { + this.flairs = flairs; + notifyDataSetChanged(); + } + + class FlairViewHolder extends RecyclerView.ViewHolder { + View itemView; + @BindView(R.id.flair_text_view_item_flair) TextView flairTextView; + @BindView(R.id.edit_flair_image_view_item_flair) ImageView editFlairImageView; + + FlairViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + this.itemView = itemView; + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/FollowedUsersRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/FollowedUsersRecyclerViewAdapter.java new file mode 100644 index 00000000..c7a70472 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/FollowedUsersRecyclerViewAdapter.java @@ -0,0 +1,91 @@ +package ml.docilealligator.infinityforreddit.Adapter; + +import android.content.Context; +import android.content.Intent; +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 com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.request.RequestOptions; + +import java.util.List; + +import ml.docilealligator.infinityforreddit.Activity.ViewUserDetailActivity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserData; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import pl.droidsonroids.gif.GifImageView; + +public class FollowedUsersRecyclerViewAdapter extends RecyclerView.Adapter { + private List mSubscribedUserData; + private Context mContext; + private RequestManager glide; + + public FollowedUsersRecyclerViewAdapter(Context context) { + mContext = context; + glide = Glide.with(context.getApplicationContext()); + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { + return new UserViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_subscribed_thing, viewGroup, false)); + } + + @Override + public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, int i) { + viewHolder.itemView.setOnClickListener(view -> { + Intent intent = new Intent(mContext, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mSubscribedUserData.get(viewHolder.getAdapterPosition()).getName()); + mContext.startActivity(intent); + }); + if(!mSubscribedUserData.get(i).getIconUrl().equals("")) { + glide.load(mSubscribedUserData.get(i).getIconUrl()) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(glide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((UserViewHolder) viewHolder).iconGifImageView); + } else { + glide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((UserViewHolder) viewHolder).iconGifImageView); + } + ((UserViewHolder) viewHolder).subredditNameTextView.setText(mSubscribedUserData.get(i).getName()); + } + + @Override + public int getItemCount() { + if(mSubscribedUserData != null) { + return mSubscribedUserData.size(); + } + return 0; + } + + @Override + public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { + glide.clear(((UserViewHolder) holder).iconGifImageView); + } + + public void setSubscribedUsers(List subscribedUsers){ + mSubscribedUserData = subscribedUsers; + notifyDataSetChanged(); + } + + + private class UserViewHolder extends RecyclerView.ViewHolder { + private final GifImageView iconGifImageView; + private final TextView subredditNameTextView; + + public UserViewHolder(View itemView) { + super(itemView); + iconGifImageView = itemView.findViewById(R.id.subreddit_icon_gif_image_view_item_subscribed_subreddit); + subredditNameTextView = itemView.findViewById(R.id.subreddit_name_text_view_item_subscribed_subreddit); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/MessageRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/MessageRecyclerViewAdapter.java new file mode 100644 index 00000000..1e9f6ee9 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/MessageRecyclerViewAdapter.java @@ -0,0 +1,250 @@ +package ml.docilealligator.infinityforreddit.Adapter; + +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.net.Uri; +import android.text.util.Linkify; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.paging.PagedListAdapter; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.RecyclerView; + +import butterknife.BindView; +import butterknife.ButterKnife; +import io.noties.markwon.AbstractMarkwonPlugin; +import io.noties.markwon.Markwon; +import io.noties.markwon.MarkwonConfiguration; +import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; +import io.noties.markwon.linkify.LinkifyPlugin; +import ml.docilealligator.infinityforreddit.Activity.LinkResolverActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewUserDetailActivity; +import ml.docilealligator.infinityforreddit.Message; +import ml.docilealligator.infinityforreddit.NetworkState; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.ReadMessage; +import retrofit2.Retrofit; + +public class MessageRecyclerViewAdapter extends PagedListAdapter { + private static final int VIEW_TYPE_DATA = 0; + private static final int VIEW_TYPE_ERROR = 1; + private static final int VIEW_TYPE_LOADING = 2; + + private Context mContext; + private Retrofit mOauthRetrofit; + private Markwon mMarkwon; + private String mAccessToken; + private Resources mResources; + + private NetworkState networkState; + private RetryLoadingMoreCallback mRetryLoadingMoreCallback; + + public interface RetryLoadingMoreCallback { + void retryLoadingMore(); + } + + public MessageRecyclerViewAdapter(Context context, Retrofit oauthRetrofit, String accessToken, + RetryLoadingMoreCallback retryLoadingMoreCallback) { + super(DIFF_CALLBACK); + mContext = context; + mOauthRetrofit = oauthRetrofit; + mRetryLoadingMoreCallback = retryLoadingMoreCallback; + mMarkwon = Markwon.builder(mContext) + .usePlugin(new AbstractMarkwonPlugin() { + @Override + public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { + builder.linkResolver((view, link) -> { + Intent intent = new Intent(mContext, LinkResolverActivity.class); + Uri uri = Uri.parse(link); + if(uri.getScheme() == null && uri.getHost() == null) { + intent.setData(LinkResolverActivity.getRedditUriByPath(link)); + } else { + intent.setData(uri); + } + mContext.startActivity(intent); + }); + } + }) + .usePlugin(StrikethroughPlugin.create()) + .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) + .build(); + mAccessToken = accessToken; + mResources = context.getResources(); + } + + private static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() { + @Override + public boolean areItemsTheSame(@NonNull Message message, @NonNull Message t1) { + return message.getId().equals(t1.getId()); + } + + @Override + public boolean areContentsTheSame(@NonNull Message message, @NonNull Message t1) { + return message.getBody().equals(t1.getBody()); + } + }; + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + if(viewType == VIEW_TYPE_DATA) { + return new DataViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message, parent, false)); + } else if(viewType == VIEW_TYPE_ERROR) { + return new ErrorViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_error, parent, false)); + } else { + return new LoadingViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_loading, parent, false)); + } + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if(holder instanceof DataViewHolder) { + Message message = getItem(holder.getAdapterPosition()); + if(message != null) { + if(message.isNew()) { + ((DataViewHolder) holder).itemView.setBackgroundColor( + mResources.getColor(R.color.unreadMessageBackgroundColor)); + } + + if(message.wasComment()) { + ((DataViewHolder) holder).authorTextView.setTextColor(mResources.getColor(R.color.colorPrimaryDarkDayNightTheme)); + ((DataViewHolder) holder).titleTextView.setText(message.getTitle()); + } else { + ((DataViewHolder) holder).titleTextView.setVisibility(View.GONE); + } + + ((DataViewHolder) holder).authorTextView.setText(message.getAuthor()); + String subject = message.getSubject().substring(0, 1).toUpperCase() + message.getSubject().substring(1); + ((DataViewHolder) holder).subjectTextView.setText(subject); + mMarkwon.setMarkdown(((DataViewHolder) holder).contentCustomMarkwonView, message.getBody()); + + ((DataViewHolder) holder).itemView.setOnClickListener(view -> { + if(message.getContext() != null && !message.getContext().equals("")) { + Uri uri = LinkResolverActivity.getRedditUriByPath(message.getContext()); + Intent intent = new Intent(mContext, LinkResolverActivity.class); + intent.setData(uri); + mContext.startActivity(intent); + } + + if(message.isNew()) { + ((DataViewHolder) holder).itemView.setBackgroundColor(mResources.getColor(R.color.backgroundColor)); + message.setNew(false); + + ReadMessage.readMessage(mOauthRetrofit, mAccessToken, message.getFullname(), + new ReadMessage.ReadMessageListener() { + @Override + public void readSuccess() {} + + @Override + public void readFailed() { + message.setNew(true); + ((DataViewHolder) holder).itemView.setBackgroundColor(mResources.getColor(R.color.unreadMessageBackgroundColor)); + } + }); + } + }); + + ((DataViewHolder) holder).authorTextView.setOnClickListener(view -> { + if(message.wasComment()) { + Intent intent = new Intent(mContext, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, message.getAuthor()); + mContext.startActivity(intent); + } + }); + + ((DataViewHolder) holder).contentCustomMarkwonView.setOnClickListener(view -> ((DataViewHolder) holder).itemView.performClick()); + } + } + } + + @Override + public int getItemViewType(int position) { + // Reached at the end + if (hasExtraRow() && position == getItemCount() - 1) { + if (networkState.getStatus() == NetworkState.Status.LOADING) { + return VIEW_TYPE_LOADING; + } else { + return VIEW_TYPE_ERROR; + } + } else { + return VIEW_TYPE_DATA; + } + } + + @Override + public int getItemCount() { + if(hasExtraRow()) { + return super.getItemCount() + 1; + } + return super.getItemCount(); + } + + @Override + public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { + super.onViewRecycled(holder); + if(holder instanceof DataViewHolder) { + ((DataViewHolder) holder).itemView.setBackgroundColor(mResources.getColor(R.color.backgroundColor)); + ((DataViewHolder) holder).titleTextView.setVisibility(View.VISIBLE); + ((DataViewHolder) holder).authorTextView.setTextColor(mResources.getColor(R.color.primaryTextColor)); + } + } + + private boolean hasExtraRow() { + return networkState != null && networkState.getStatus() != NetworkState.Status.SUCCESS; + } + + public void setNetworkState(NetworkState newNetworkState) { + NetworkState previousState = this.networkState; + boolean previousExtraRow = hasExtraRow(); + this.networkState = newNetworkState; + boolean newExtraRow = hasExtraRow(); + if (previousExtraRow != newExtraRow) { + if (previousExtraRow) { + notifyItemRemoved(super.getItemCount()); + } else { + notifyItemInserted(super.getItemCount()); + } + } else if (newExtraRow && !previousState.equals(newNetworkState)) { + notifyItemChanged(getItemCount() - 1); + } + } + + class DataViewHolder extends RecyclerView.ViewHolder { + View itemView; + @BindView(R.id.author_text_view_item_message) TextView authorTextView; + @BindView(R.id.subject_text_view_item_message) TextView subjectTextView; + @BindView(R.id.title_text_view_item_message) TextView titleTextView; + @BindView(R.id.content_custom_markwon_view_item_message) TextView contentCustomMarkwonView; + + DataViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + this.itemView = itemView; + } + } + + class ErrorViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.error_text_view_item_footer_error) TextView errorTextView; + @BindView(R.id.retry_button_item_footer_error) Button retryButton; + + ErrorViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + errorTextView.setText(R.string.load_comments_failed); + retryButton.setOnClickListener(view -> mRetryLoadingMoreCallback.retryLoadingMore()); + } + } + + class LoadingViewHolder extends RecyclerView.ViewHolder { + LoadingViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java new file mode 100644 index 00000000..cb4c5950 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java @@ -0,0 +1,878 @@ +package ml.docilealligator.infinityforreddit.Adapter; + +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.graphics.ColorFilter; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.cardview.widget.CardView; +import androidx.core.content.ContextCompat; +import androidx.paging.PagedListAdapter; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestBuilder; +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.RequestOptions; +import com.bumptech.glide.request.target.Target; +import com.google.android.material.card.MaterialCardView; +import com.libRG.CustomTextView; + +import org.greenrobot.eventbus.EventBus; + +import butterknife.BindView; +import butterknife.ButterKnife; +import jp.wasabeef.glide.transformations.BlurTransformation; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import ml.docilealligator.infinityforreddit.Activity.CommentActivity; +import ml.docilealligator.infinityforreddit.Activity.FilteredThingActivity; +import ml.docilealligator.infinityforreddit.Activity.LinkResolverActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewImageActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewPostDetailActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewSubredditDetailActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewUserDetailActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewVideoActivity; +import ml.docilealligator.infinityforreddit.AsyncTask.LoadSubredditIconAsyncTask; +import ml.docilealligator.infinityforreddit.AsyncTask.LoadUserDataAsyncTask; +import ml.docilealligator.infinityforreddit.CustomView.AspectRatioGifImageView; +import ml.docilealligator.infinityforreddit.Event.PostUpdateEventToDetailActivity; +import ml.docilealligator.infinityforreddit.NetworkState; +import ml.docilealligator.infinityforreddit.Post; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.RedditUtils; +import ml.docilealligator.infinityforreddit.SaveThing; +import ml.docilealligator.infinityforreddit.User.UserDao; +import ml.docilealligator.infinityforreddit.VoteThing; +import retrofit2.Retrofit; + +/** + * Created by alex on 2/25/18. + */ + +public class PostRecyclerViewAdapter extends PagedListAdapter { + private Context mContext; + private Retrofit mOauthRetrofit; + private Retrofit mRetrofit; + private String mAccessToken; + private RequestManager mGlide; + private RedditDataRoomDatabase mRedditDataRoomDatabase; + private UserDao mUserDao; + private boolean canStartActivity = true; + private int mPostType; + private boolean mDisplaySubredditName; + private boolean mNeedBlurNSFW; + private boolean mNeedBlurSpoiler; + + private static final int VIEW_TYPE_DATA = 0; + private static final int VIEW_TYPE_ERROR = 1; + private static final int VIEW_TYPE_LOADING = 2; + + private NetworkState networkState; + private Callback mCallback; + + public interface Callback { + void retryLoadingMore(); + void typeChipClicked(int filter); + } + + public PostRecyclerViewAdapter(Context context, Retrofit oauthRetrofit, Retrofit retrofit, + RedditDataRoomDatabase redditDataRoomDatabase, String accessToken, + int postType, boolean displaySubredditName, boolean needBlurNSFW, + boolean needBlurSpoiler, Callback callback) { + super(DIFF_CALLBACK); + if(context != null) { + mContext = context; + mOauthRetrofit = oauthRetrofit; + mRetrofit = retrofit; + mAccessToken = accessToken; + mPostType = postType; + mDisplaySubredditName = displaySubredditName; + mNeedBlurNSFW = needBlurNSFW; + mNeedBlurSpoiler = needBlurSpoiler; + mGlide = Glide.with(mContext.getApplicationContext()); + mRedditDataRoomDatabase = redditDataRoomDatabase; + mUserDao = redditDataRoomDatabase.userDao(); + mCallback = callback; + } + } + + private static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() { + @Override + public boolean areItemsTheSame(@NonNull Post post, @NonNull Post t1) { + return post.getId().equals(t1.getId()); + } + + @Override + public boolean areContentsTheSame(@NonNull Post post, @NonNull Post t1) { + return post.getTitle().equals(t1.getTitle()) && !(post.getSelfText() != null && t1.getSelfText() != null + && !post.getSelfText().equals(t1.getSelfText())) + && post.getScore() == t1.getScore() && post.getVoteType() == t1.getVoteType(); + } + }; + + public void setCanStartActivity(boolean canStartActivity) { + this.canStartActivity = canStartActivity; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + if(viewType == VIEW_TYPE_DATA) { + CardView cardView = (CardView) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_post, parent, false); + return new DataViewHolder(cardView); + } else if(viewType == VIEW_TYPE_ERROR) { + RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_error, parent, false); + return new ErrorViewHolder(relativeLayout); + } else { + RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_loading, parent, false); + return new LoadingViewHolder(relativeLayout); + } + } + + @Override + public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) { + if(holder instanceof DataViewHolder) { + Post post = getItem(position); + if(post != null) { + final String id = post.getFullName(); + final String subredditNamePrefixed = post.getSubredditNamePrefixed(); + String subredditName = subredditNamePrefixed.substring(2); + String authorPrefixed = "u/" + post.getAuthor(); + final String postTime = post.getPostTime(); + final String title = post.getTitle(); + final String permalink = post.getPermalink(); + int voteType = post.getVoteType(); + int gilded = post.getGilded(); + boolean nsfw = post.isNSFW(); + boolean spoiler = post.isSpoiler(); + String flair = post.getFlair(); + boolean isArchived = post.isArchived(); + + ((DataViewHolder) holder).cardView.setOnClickListener(view -> { + if(canStartActivity) { + canStartActivity = false; + + Intent intent = new Intent(mContext, ViewPostDetailActivity.class); + intent.putExtra(ViewPostDetailActivity.EXTRA_POST_DATA, post); + intent.putExtra(ViewPostDetailActivity.EXTRA_POST_LIST_POSITION, position); + mContext.startActivity(intent); + } + }); + + if(mDisplaySubredditName) { + if(authorPrefixed.equals(subredditNamePrefixed)) { + if(post.getAuthorIconUrl() == null) { + new LoadUserDataAsyncTask(mUserDao, post.getAuthor(), mRetrofit, iconImageUrl -> { + if(mContext != null && getItemCount() > 0) { + if(iconImageUrl == null || iconImageUrl.equals("")) { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((DataViewHolder) holder).iconGifImageView); + } else { + mGlide.load(iconImageUrl) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((DataViewHolder) holder).iconGifImageView); + } + + if(holder.getAdapterPosition() >= 0) { + post.setAuthorIconUrl(iconImageUrl); + } + } + }).execute(); + } else if(!post.getAuthorIconUrl().equals("")) { + mGlide.load(post.getAuthorIconUrl()) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((DataViewHolder) holder).iconGifImageView); + } else { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((DataViewHolder) holder).iconGifImageView); + } + } else { + if(post.getSubredditIconUrl() == null) { + new LoadSubredditIconAsyncTask(mRedditDataRoomDatabase, subredditName, mRetrofit, + iconImageUrl -> { + if(mContext != null && getItemCount() > 0) { + if(iconImageUrl == null || iconImageUrl.equals("")) { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((DataViewHolder) holder).iconGifImageView); + } else { + mGlide.load(iconImageUrl) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((DataViewHolder) holder).iconGifImageView); + } + + if(holder.getAdapterPosition() >= 0) { + post.setSubredditIconUrl(iconImageUrl); + } + } + }).execute(); + } else if(!post.getSubredditIconUrl().equals("")) { + mGlide.load(post.getSubredditIconUrl()) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((DataViewHolder) holder).iconGifImageView); + } else { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((DataViewHolder) holder).iconGifImageView); + } + } + + ((DataViewHolder) holder).nameTextView.setTextColor(mContext.getResources().getColor(R.color.colorAccent)); + ((DataViewHolder) holder).nameTextView.setText(subredditNamePrefixed); + + ((DataViewHolder) holder).iconNameLinearLayout.setOnClickListener(view -> { + if(canStartActivity) { + canStartActivity = false; + if(post.getSubredditNamePrefixed().startsWith("u/")) { + Intent intent = new Intent(mContext, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, + post.getSubredditNamePrefixed().substring(2)); + mContext.startActivity(intent); + } else { + Intent intent = new Intent(mContext, ViewSubredditDetailActivity.class); + intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, + post.getSubredditNamePrefixed().substring(2)); + mContext.startActivity(intent); + } + } + }); + } else { + if(post.getAuthorIconUrl() == null) { + String authorName = post.getAuthor().equals("[deleted]") ? post.getSubredditNamePrefixed().substring(2) : post.getAuthor(); + new LoadUserDataAsyncTask(mUserDao, authorName, mRetrofit, iconImageUrl -> { + if(mContext != null && getItemCount() > 0) { + if(iconImageUrl == null || iconImageUrl.equals("")) { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((DataViewHolder) holder).iconGifImageView); + } else { + mGlide.load(iconImageUrl) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((DataViewHolder) holder).iconGifImageView); + } + + if(holder.getAdapterPosition() >= 0) { + post.setAuthorIconUrl(iconImageUrl); + } + } + }).execute(); + } else if(!post.getAuthorIconUrl().equals("")) { + mGlide.load(post.getAuthorIconUrl()) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((DataViewHolder) holder).iconGifImageView); + } else { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((DataViewHolder) holder).iconGifImageView); + } + + ((DataViewHolder) holder).nameTextView.setTextColor(mContext.getResources().getColor(R.color.colorPrimaryDarkDayNightTheme)); + ((DataViewHolder) holder).nameTextView.setText(authorPrefixed); + + ((DataViewHolder) holder).iconNameLinearLayout.setOnClickListener(view -> { + if(canStartActivity) { + canStartActivity = false; + Intent intent = new Intent(mContext, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, post.getAuthor()); + mContext.startActivity(intent); + } + }); + } + + ((DataViewHolder) holder).postTimeTextView.setText(postTime); + ((DataViewHolder) holder).titleTextView.setText(title); + ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + post.getVoteType())); + + if(gilded > 0) { + ((DataViewHolder) holder).gildedImageView.setVisibility(View.VISIBLE); + ((DataViewHolder) holder).gildedNumberTextView.setVisibility(View.VISIBLE); + String gildedNumber = mContext.getResources().getString(R.string.gilded_count, gilded); + ((DataViewHolder) holder).gildedNumberTextView.setText(gildedNumber); + } + + if(post.isLocked()) { + ((DataViewHolder) holder).lockedImageView.setVisibility(View.VISIBLE); + } + + if(nsfw) { + if(!(mContext instanceof FilteredThingActivity)) { + ((DataViewHolder) holder).nsfwTextView.setOnClickListener(view -> { + Intent intent = new Intent(mContext, FilteredThingActivity.class); + intent.putExtra(FilteredThingActivity.EXTRA_NAME, post.getSubredditNamePrefixed().substring(2)); + intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); + intent.putExtra(FilteredThingActivity.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_HOT); + intent.putExtra(FilteredThingActivity.EXTRA_FILTER, Post.NSFW_TYPE); + mContext.startActivity(intent); + }); + } + ((DataViewHolder) holder).nsfwTextView.setVisibility(View.VISIBLE); + } + + if(spoiler || flair != null) { + ((DataViewHolder) holder).spoilerFlairLinearLayout.setVisibility(View.VISIBLE); + } + + if(spoiler) { + ((DataViewHolder) holder).spoilerTextView.setVisibility(View.VISIBLE); + } + + if(flair != null) { + ((DataViewHolder) holder).flairTextView.setVisibility(View.VISIBLE); + ((DataViewHolder) holder).flairTextView.setText(flair); + } + + switch (voteType) { + case 1: + //Upvoted + ((DataViewHolder) holder).upvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.upvoted)); + break; + case -1: + //Downvoted + ((DataViewHolder) holder).downvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.downvoted)); + break; + } + + if(post.getPostType() != Post.TEXT_TYPE && post.getPostType() != Post.NO_PREVIEW_LINK_TYPE) { + ((DataViewHolder) holder).relativeLayout.setVisibility(View.VISIBLE); + ((DataViewHolder) holder).progressBar.setVisibility(View.VISIBLE); + ((DataViewHolder) holder).imageView.setVisibility(View.VISIBLE); + ((DataViewHolder) holder).imageView + .setRatio((float) post.getPreviewHeight() / post.getPreviewWidth()); + loadImage(holder, post); + } + + if(mPostType == PostDataSource.TYPE_SUBREDDIT && !mDisplaySubredditName && post.isStickied()) { + ((DataViewHolder) holder).stickiedPostImageView.setVisibility(View.VISIBLE); + mGlide.load(R.drawable.ic_thumbtack_24dp).into(((DataViewHolder) holder).stickiedPostImageView); + } + + if(isArchived) { + ((DataViewHolder) holder).archivedImageView.setVisibility(View.VISIBLE); + + ((DataViewHolder) holder).upvoteButton + .setColorFilter(ContextCompat.getColor(mContext, R.color.voteAndReplyUnavailableVoteButtonColor), android.graphics.PorterDuff.Mode.SRC_IN); + ((DataViewHolder) holder).downvoteButton + .setColorFilter(ContextCompat.getColor(mContext, R.color.voteAndReplyUnavailableVoteButtonColor), android.graphics.PorterDuff.Mode.SRC_IN); + } + + if(post.isCrosspost()) { + ((DataViewHolder) holder).crosspostImageView.setVisibility(View.VISIBLE); + } + + if(!(mContext instanceof FilteredThingActivity)) { + ((DataViewHolder) holder).typeTextView.setOnClickListener(view -> mCallback.typeChipClicked(post.getPostType())); + } + + switch (post.getPostType()) { + case Post.IMAGE_TYPE: + ((DataViewHolder) holder).typeTextView.setText(R.string.image); + + final String imageUrl = post.getUrl(); + ((DataViewHolder) holder).imageView.setOnClickListener(view -> { + Intent intent = new Intent(mContext, ViewImageActivity.class); + intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, imageUrl); + intent.putExtra(ViewImageActivity.TITLE_KEY, title); + intent.putExtra(ViewImageActivity.FILE_NAME_KEY, subredditNamePrefixed.substring(2) + + "-" + id.substring(3)); + mContext.startActivity(intent); + }); + break; + case Post.LINK_TYPE: + ((DataViewHolder) holder).typeTextView.setText(R.string.link); + + ((DataViewHolder) holder).linkTextView.setVisibility(View.VISIBLE); + String domain = Uri.parse(post.getUrl()).getHost(); + ((DataViewHolder) holder).linkTextView.setText(domain); + + ((DataViewHolder) holder).imageView.setOnClickListener(view -> { + Intent intent = new Intent(mContext, LinkResolverActivity.class); + Uri uri = Uri.parse(post.getUrl()); + if(uri.getScheme() == null && uri.getHost() == null) { + intent.setData(LinkResolverActivity.getRedditUriByPath(post.getUrl())); + } else { + intent.setData(uri); + } + mContext.startActivity(intent); + }); + break; + case Post.GIF_VIDEO_TYPE: + ((DataViewHolder) holder).typeTextView.setText(R.string.gif); + + final Uri gifVideoUri = Uri.parse(post.getVideoUrl()); + ((DataViewHolder) holder).imageView.setOnClickListener(view -> { + Intent intent = new Intent(mContext, ViewVideoActivity.class); + intent.setData(gifVideoUri); + intent.putExtra(ViewVideoActivity.TITLE_KEY, title); + intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, subredditName); + intent.putExtra(ViewVideoActivity.ID_KEY, id); + mContext.startActivity(intent); + }); + break; + case Post.VIDEO_TYPE: + ((DataViewHolder) holder).typeTextView.setText(R.string.video); + + final Uri videoUri = Uri.parse(post.getVideoUrl()); + ((DataViewHolder) holder).imageView.setOnClickListener(view -> { + Intent intent = new Intent(mContext, ViewVideoActivity.class); + intent.setData(videoUri); + intent.putExtra(ViewVideoActivity.TITLE_KEY, title); + intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, subredditName); + intent.putExtra(ViewVideoActivity.ID_KEY, id); + mContext.startActivity(intent); + }); + break; + case Post.NO_PREVIEW_LINK_TYPE: + ((DataViewHolder) holder).typeTextView.setText(R.string.link); + + String noPreviewLinkUrl = post.getUrl(); + ((DataViewHolder) holder).linkTextView.setVisibility(View.VISIBLE); + String noPreviewLinkDomain = Uri.parse(noPreviewLinkUrl).getHost(); + ((DataViewHolder) holder).linkTextView.setText(noPreviewLinkDomain); + ((DataViewHolder) holder).noPreviewLinkImageView.setVisibility(View.VISIBLE); + ((DataViewHolder) holder).noPreviewLinkImageView.setOnClickListener(view -> { + Intent intent = new Intent(mContext, LinkResolverActivity.class); + Uri uri = Uri.parse(post.getUrl()); + if(uri.getScheme() == null && uri.getHost() == null) { + intent.setData(LinkResolverActivity.getRedditUriByPath(post.getUrl())); + } else { + intent.setData(uri); + } + mContext.startActivity(intent); + }); + break; + case Post.TEXT_TYPE: + ((DataViewHolder) holder).typeTextView.setText(R.string.text); + break; + } + + ((DataViewHolder) holder).upvoteButton.setOnClickListener(view -> { + if(mAccessToken == null) { + Toast.makeText(mContext, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + if(isArchived) { + Toast.makeText(mContext, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); + return; + } + + ColorFilter previousUpvoteButtonColorFilter = ((DataViewHolder) holder).upvoteButton.getColorFilter(); + ColorFilter previousDownvoteButtonColorFilter = ((DataViewHolder) holder).downvoteButton.getColorFilter(); + int previousScoreTextViewColor = ((DataViewHolder) holder).scoreTextView.getCurrentTextColor(); + + int previousVoteType = post.getVoteType(); + String newVoteType; + + ((DataViewHolder) holder).downvoteButton.clearColorFilter(); + + if(previousUpvoteButtonColorFilter == null) { + //Not upvoted before + post.setVoteType(1); + newVoteType = RedditUtils.DIR_UPVOTE; + ((DataViewHolder) holder).upvoteButton + .setColorFilter(ContextCompat.getColor(mContext, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.upvoted)); + } else { + //Upvoted before + post.setVoteType(0); + newVoteType = RedditUtils.DIR_UNVOTE; + ((DataViewHolder) holder).upvoteButton.clearColorFilter(); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); + } + + ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + post.getVoteType())); + + VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { + @Override + public void onVoteThingSuccess(int position1) { + if(newVoteType.equals(RedditUtils.DIR_UPVOTE)) { + post.setVoteType(1); + ((DataViewHolder) holder).upvoteButton + .setColorFilter(ContextCompat.getColor(mContext, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.upvoted)); + } else { + post.setVoteType(0); + ((DataViewHolder) holder).upvoteButton.clearColorFilter(); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); + } + + ((DataViewHolder) holder).downvoteButton.clearColorFilter(); + ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + post.getVoteType())); + + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + + @Override + public void onVoteThingFail(int position1) { + Toast.makeText(mContext, R.string.vote_failed, Toast.LENGTH_SHORT).show(); + post.setVoteType(previousVoteType); + ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + previousVoteType)); + ((DataViewHolder) holder).upvoteButton.setColorFilter(previousUpvoteButtonColorFilter); + ((DataViewHolder) holder).downvoteButton.setColorFilter(previousDownvoteButtonColorFilter); + ((DataViewHolder) holder).scoreTextView.setTextColor(previousScoreTextViewColor); + + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + }, id, newVoteType, holder.getAdapterPosition()); + }); + + ((DataViewHolder) holder).downvoteButton.setOnClickListener(view -> { + if(mAccessToken == null) { + Toast.makeText(mContext, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + if(isArchived) { + Toast.makeText(mContext, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); + return; + } + + ColorFilter previousUpvoteButtonColorFilter = ((DataViewHolder) holder).upvoteButton.getColorFilter(); + ColorFilter previousDownvoteButtonColorFilter = ((DataViewHolder) holder).downvoteButton.getColorFilter(); + int previousScoreTextViewColor = ((DataViewHolder) holder).scoreTextView.getCurrentTextColor(); + + int previousVoteType = post.getVoteType(); + String newVoteType; + + ((DataViewHolder) holder).upvoteButton.clearColorFilter(); + + if(previousDownvoteButtonColorFilter == null) { + //Not downvoted before + post.setVoteType(-1); + newVoteType = RedditUtils.DIR_DOWNVOTE; + ((DataViewHolder) holder).downvoteButton + .setColorFilter(ContextCompat.getColor(mContext, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.downvoted)); + } else { + //Downvoted before + post.setVoteType(0); + newVoteType = RedditUtils.DIR_UNVOTE; + ((DataViewHolder) holder).downvoteButton.clearColorFilter(); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); + } + + ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + post.getVoteType())); + + VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { + @Override + public void onVoteThingSuccess(int position1) { + if(newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) { + post.setVoteType(-1); + ((DataViewHolder) holder).downvoteButton + .setColorFilter(ContextCompat.getColor(mContext, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.downvoted)); + } else { + post.setVoteType(0); + ((DataViewHolder) holder).downvoteButton.clearColorFilter(); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); + } + + ((DataViewHolder) holder).upvoteButton.clearColorFilter(); + ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + post.getVoteType())); + + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + + @Override + public void onVoteThingFail(int position1) { + Toast.makeText(mContext, R.string.vote_failed, Toast.LENGTH_SHORT).show(); + post.setVoteType(previousVoteType); + ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + previousVoteType)); + ((DataViewHolder) holder).upvoteButton.setColorFilter(previousUpvoteButtonColorFilter); + ((DataViewHolder) holder).downvoteButton.setColorFilter(previousDownvoteButtonColorFilter); + ((DataViewHolder) holder).scoreTextView.setTextColor(previousScoreTextViewColor); + + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + }, id, newVoteType, holder.getAdapterPosition()); + }); + + ((DataViewHolder) holder).commentButton.setOnClickListener(view -> { + if(mAccessToken == null) { + Toast.makeText(mContext, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + Intent intent = new Intent(mContext, CommentActivity.class); + intent.putExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY, post.getFullName()); + intent.putExtra(CommentActivity.EXTRA_COMMENT_PARENT_TEXT_KEY, post.getTitle()); + intent.putExtra(CommentActivity.EXTRA_IS_REPLYING_KEY, false); + intent.putExtra(CommentActivity.EXTRA_PARENT_DEPTH_KEY, 0); + mContext.startActivity(intent); + }); + + ((DataViewHolder) holder).commentsCountTextView.setText(Integer.toString(post.getnComments())); + + if(post.isSaved()) { + ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); + } else { + ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); + } + + ((DataViewHolder) holder).saveButton.setOnClickListener(view -> { + if(mAccessToken == null) { + Toast.makeText(mContext, R.string.login_first, Toast.LENGTH_SHORT).show(); + return; + } + + if(post.isSaved()) { + ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); + SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, post.getFullName(), + new SaveThing.SaveThingListener() { + @Override + public void success() { + post.setSaved(false); + ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); + Toast.makeText(mContext, R.string.post_unsaved_success, Toast.LENGTH_SHORT).show(); + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + + @Override + public void failed() { + post.setSaved(true); + ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); + Toast.makeText(mContext, R.string.post_unsaved_failed, Toast.LENGTH_SHORT).show(); + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + }); + } else { + ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); + SaveThing.saveThing(mOauthRetrofit, mAccessToken, post.getFullName(), + new SaveThing.SaveThingListener() { + @Override + public void success() { + post.setSaved(true); + ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); + Toast.makeText(mContext, R.string.post_saved_success, Toast.LENGTH_SHORT).show(); + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + + @Override + public void failed() { + post.setSaved(false); + ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); + Toast.makeText(mContext, R.string.post_saved_failed, Toast.LENGTH_SHORT).show(); + EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); + } + }); + } + }); + + ((DataViewHolder) holder).shareButton.setOnClickListener(view -> { + try { + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("text/plain"); + String extraText = title + "\n" + permalink; + intent.putExtra(Intent.EXTRA_TEXT, extraText); + mContext.startActivity(Intent.createChooser(intent, mContext.getString(R.string.share))); + } catch (ActivityNotFoundException e) { + Toast.makeText(mContext, R.string.no_activity_found_for_share, Toast.LENGTH_SHORT).show(); + } + }); + } + } + } + + private void loadImage(final RecyclerView.ViewHolder holder, final Post post) { + RequestBuilder imageRequestBuilder = mGlide.load(post.getPreviewUrl()).listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + ((DataViewHolder) holder).progressBar.setVisibility(View.GONE); + ((DataViewHolder) holder).errorRelativeLayout.setVisibility(View.VISIBLE); + ((DataViewHolder)holder).errorRelativeLayout.setOnClickListener(view -> { + ((DataViewHolder) holder).progressBar.setVisibility(View.VISIBLE); + ((DataViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); + loadImage(holder, post); + }); + return false; + } + + @Override + public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + ((DataViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); + ((DataViewHolder) holder).progressBar.setVisibility(View.GONE); + return false; + } + }); + + if((post.isNSFW() && mNeedBlurNSFW) || post.isSpoiler() && mNeedBlurSpoiler) { + imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 2))) + .into(((DataViewHolder) holder).imageView); + } else { + imageRequestBuilder.into(((DataViewHolder) holder).imageView); + } + } + + @Override + public int getItemViewType(int position) { + // Reached at the end + if (hasExtraRow() && position == getItemCount() - 1) { + if (networkState.getStatus() == NetworkState.Status.LOADING) { + return VIEW_TYPE_LOADING; + } else { + return VIEW_TYPE_ERROR; + } + } else { + return VIEW_TYPE_DATA; + } + } + + @Override + public int getItemCount() { + if(hasExtraRow()) { + return super.getItemCount() + 1; + } + return super.getItemCount(); + } + + public void setBlurNSFW(boolean needBlurNSFW) { + mNeedBlurNSFW = needBlurNSFW; + } + + public void setBlurSpoiler(boolean needBlurSpoiler) { + mNeedBlurSpoiler = needBlurSpoiler; + } + + private boolean hasExtraRow() { + return networkState != null && networkState.getStatus() != NetworkState.Status.SUCCESS; + } + + public void setNetworkState(NetworkState newNetworkState) { + NetworkState previousState = this.networkState; + boolean previousExtraRow = hasExtraRow(); + this.networkState = newNetworkState; + boolean newExtraRow = hasExtraRow(); + if (previousExtraRow != newExtraRow) { + if (previousExtraRow) { + notifyItemRemoved(super.getItemCount()); + } else { + notifyItemInserted(super.getItemCount()); + } + } else if (newExtraRow && !previousState.equals(newNetworkState)) { + notifyItemChanged(getItemCount() - 1); + } + } + + class DataViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.card_view_item_post) MaterialCardView cardView; + @BindView(R.id.icon_name_linear_layout_view_item_post) LinearLayout iconNameLinearLayout; + @BindView(R.id.icon_gif_image_view_item_post) AspectRatioGifImageView iconGifImageView; + @BindView(R.id.name_text_view_item_post) TextView nameTextView; + @BindView(R.id.stickied_post_image_view_item_post) ImageView stickiedPostImageView; + @BindView(R.id.post_time_text_view_best_item_post) TextView postTimeTextView; + @BindView(R.id.title_text_view_best_item_post) TextView titleTextView; + @BindView(R.id.type_text_view_item_post) CustomTextView typeTextView; + @BindView(R.id.gilded_image_view_item_post) ImageView gildedImageView; + @BindView(R.id.gilded_number_text_view_item_post) TextView gildedNumberTextView; + @BindView(R.id.archived_image_view_item_post) ImageView archivedImageView; + @BindView(R.id.locked_image_view_item_post) ImageView lockedImageView; + @BindView(R.id.crosspost_image_view_item_post) ImageView crosspostImageView; + @BindView(R.id.nsfw_text_view_item_post) CustomTextView nsfwTextView; + @BindView(R.id.spoiler_flair_linear_layout_item_post) LinearLayout spoilerFlairLinearLayout; + @BindView(R.id.spoiler_custom_text_view_item_post) CustomTextView spoilerTextView; + @BindView(R.id.flair_custom_text_view_item_post) CustomTextView flairTextView; + @BindView(R.id.link_text_view_item_post) TextView linkTextView; + @BindView(R.id.image_view_wrapper_item_post) RelativeLayout relativeLayout; + @BindView(R.id.progress_bar_item_post) ProgressBar progressBar; + @BindView(R.id.image_view_best_post_item) AspectRatioGifImageView imageView; + @BindView(R.id.load_image_error_relative_layout_item_post) RelativeLayout errorRelativeLayout; + @BindView(R.id.image_view_no_preview_link_item_post) ImageView noPreviewLinkImageView; + @BindView(R.id.plus_button_item_post) ImageView upvoteButton; + @BindView(R.id.score_text_view_item_post) TextView scoreTextView; + @BindView(R.id.minus_button_item_post) ImageView downvoteButton; + @BindView(R.id.comment_button_item_post) ImageView commentButton; + @BindView(R.id.comments_count_item_post) TextView commentsCountTextView; + @BindView(R.id.save_button_item_post) ImageView saveButton; + @BindView(R.id.share_button_item_post) ImageView shareButton; + + DataViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + scoreTextView.setOnClickListener(view -> { + //Do nothing in order to prevent clicking this to start ViewPostDetailActivity + }); + } + } + + class ErrorViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.error_text_view_item_footer_error) TextView errorTextView; + @BindView(R.id.retry_button_item_footer_error) Button retryButton; + + ErrorViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + errorTextView.setText(R.string.load_posts_error); + retryButton.setOnClickListener(view -> mCallback.retryLoadingMore()); + } + } + + class LoadingViewHolder extends RecyclerView.ViewHolder { + LoadingViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + } + + @Override + public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { + if(holder instanceof DataViewHolder) { + mGlide.clear(((DataViewHolder) holder).imageView); + mGlide.clear(((DataViewHolder) holder).iconGifImageView); + ((DataViewHolder) holder).stickiedPostImageView.setVisibility(View.GONE); + ((DataViewHolder) holder).relativeLayout.setVisibility(View.GONE); + ((DataViewHolder) holder).gildedImageView.setVisibility(View.GONE); + ((DataViewHolder) holder).gildedNumberTextView.setVisibility(View.GONE); + ((DataViewHolder) holder).crosspostImageView.setVisibility(View.GONE); + ((DataViewHolder) holder).archivedImageView.setVisibility(View.GONE); + ((DataViewHolder) holder).lockedImageView.setVisibility(View.GONE); + ((DataViewHolder) holder).nsfwTextView.setVisibility(View.GONE); + ((DataViewHolder) holder).spoilerFlairLinearLayout.setVisibility(View.GONE); + ((DataViewHolder) holder).spoilerTextView.setVisibility(View.GONE); + ((DataViewHolder) holder).flairTextView.setVisibility(View.GONE); + ((DataViewHolder) holder).linkTextView.setVisibility(View.GONE); + ((DataViewHolder) holder).progressBar.setVisibility(View.GONE); + ((DataViewHolder) holder).imageView.setVisibility(View.GONE); + ((DataViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); + ((DataViewHolder) holder).noPreviewLinkImageView.setVisibility(View.GONE); + ((DataViewHolder) holder).upvoteButton.clearColorFilter(); + ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); + ((DataViewHolder) holder).downvoteButton.clearColorFilter(); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/RulesRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/RulesRecyclerViewAdapter.java new file mode 100644 index 00000000..0cf5e337 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/RulesRecyclerViewAdapter.java @@ -0,0 +1,95 @@ +package ml.docilealligator.infinityforreddit.Adapter; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.text.util.Linkify; +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.ArrayList; + +import butterknife.BindView; +import butterknife.ButterKnife; +import io.noties.markwon.AbstractMarkwonPlugin; +import io.noties.markwon.Markwon; +import io.noties.markwon.MarkwonConfiguration; +import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; +import io.noties.markwon.linkify.LinkifyPlugin; +import ml.docilealligator.infinityforreddit.Activity.LinkResolverActivity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.Rule; + +public class RulesRecyclerViewAdapter extends RecyclerView.Adapter { + private Markwon markwon; + private ArrayList rules; + + public RulesRecyclerViewAdapter(Context context) { + markwon = Markwon.builder(context) + .usePlugin(new AbstractMarkwonPlugin() { + @Override + public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { + builder.linkResolver((view, link) -> { + Intent intent = new Intent(context, LinkResolverActivity.class); + Uri uri = Uri.parse(link); + if(uri.getScheme() == null && uri.getHost() == null) { + intent.setData(LinkResolverActivity.getRedditUriByPath(link)); + } else { + intent.setData(uri); + } + context.startActivity(intent); + }); + } + }) + .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) + .usePlugin(StrikethroughPlugin.create()) + .build(); + } + + @NonNull + @Override + public RuleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new RuleViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_rule, parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull RuleViewHolder holder, int position) { + holder.shortNameTextView.setText(rules.get(holder.getAdapterPosition()).getShortName()); + if(rules.get(holder.getAdapterPosition()).getDescriptionHtml() == null) { + holder.descriptionMarkwonView.setVisibility(View.GONE); + } else { + markwon.setMarkdown(holder.descriptionMarkwonView, rules.get(holder.getAdapterPosition()).getDescriptionHtml()); + } + } + + @Override + public int getItemCount() { + return rules == null ? 0 : rules.size(); + } + + @Override + public void onViewRecycled(@NonNull RuleViewHolder holder) { + super.onViewRecycled(holder); + holder.descriptionMarkwonView.setVisibility(View.VISIBLE); + } + + public void changeDataset(ArrayList rules) { + this.rules = rules; + notifyDataSetChanged(); + } + + class RuleViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.short_name_text_view_item_rule) TextView shortNameTextView; + @BindView(R.id.description_markwon_view_item_rule) TextView descriptionMarkwonView; + + RuleViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/SubredditListingRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/SubredditListingRecyclerViewAdapter.java new file mode 100644 index 00000000..613d551d --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/SubredditListingRecyclerViewAdapter.java @@ -0,0 +1,231 @@ +package ml.docilealligator.infinityforreddit.Adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.paging.PagedListAdapter; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.request.RequestOptions; + +import butterknife.BindView; +import butterknife.ButterKnife; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import ml.docilealligator.infinityforreddit.AsyncTask.CheckIsSubscribedToSubredditAsyncTask; +import ml.docilealligator.infinityforreddit.NetworkState; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditData; +import ml.docilealligator.infinityforreddit.SubredditSubscription; +import pl.droidsonroids.gif.GifImageView; +import retrofit2.Retrofit; + +public class SubredditListingRecyclerViewAdapter extends PagedListAdapter { + public interface Callback { + void retryLoadingMore(); + void subredditSelected(String subredditName, String iconUrl); + } + + private RequestManager glide; + + private static final int VIEW_TYPE_DATA = 0; + private static final int VIEW_TYPE_ERROR = 1; + private static final int VIEW_TYPE_LOADING = 2; + + private Context context; + private Retrofit oauthRetrofit; + private Retrofit retrofit; + private String accessToken; + private String accountName; + private RedditDataRoomDatabase redditDataRoomDatabase; + + private NetworkState networkState; + private Callback callback; + + public SubredditListingRecyclerViewAdapter(Context context, Retrofit oauthRetrofit, Retrofit retrofit, + String accessToken, String accountName, + RedditDataRoomDatabase redditDataRoomDatabase, + Callback callback) { + super(DIFF_CALLBACK); + this.context = context; + this.oauthRetrofit = oauthRetrofit; + this.retrofit = retrofit; + this.accessToken = accessToken; + this.accountName = accountName; + this.redditDataRoomDatabase = redditDataRoomDatabase; + this.callback = callback; + glide = Glide.with(context.getApplicationContext()); + } + + private static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() { + @Override + public boolean areItemsTheSame(@NonNull SubredditData oldItem, @NonNull SubredditData newItem) { + return oldItem.getId().equals(newItem.getId()); + } + + @Override + public boolean areContentsTheSame(@NonNull SubredditData oldItem, @NonNull SubredditData newItem) { + return true; + } + }; + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + if(viewType == VIEW_TYPE_DATA) { + ConstraintLayout constraintLayout = (ConstraintLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_subreddit_listing, parent, false); + return new DataViewHolder(constraintLayout); + } else if(viewType == VIEW_TYPE_ERROR) { + RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_error, parent, false); + return new ErrorViewHolder(relativeLayout); + } else { + RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_loading, parent, false); + return new LoadingViewHolder(relativeLayout); + } + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if(holder instanceof DataViewHolder) { + SubredditData subredditData = getItem(position); + ((DataViewHolder) holder).constraintLayout.setOnClickListener(view -> + callback.subredditSelected(subredditData.getName(), subredditData.getIconUrl())); + + if(!subredditData.getIconUrl().equals("")) { + glide.load(subredditData.getIconUrl()) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(glide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((DataViewHolder) holder).iconGifImageView); + } else { + glide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((DataViewHolder) holder).iconGifImageView); + } + + ((DataViewHolder) holder).subredditNameTextView.setText(subredditData.getName()); + + new CheckIsSubscribedToSubredditAsyncTask(redditDataRoomDatabase, subredditData.getName(), accountName, + new CheckIsSubscribedToSubredditAsyncTask.CheckIsSubscribedToSubredditListener() { + @Override + public void isSubscribed() { + ((DataViewHolder) holder).subscribeButton.setVisibility(View.GONE); + } + + @Override + public void isNotSubscribed() { + ((DataViewHolder) holder).subscribeButton.setVisibility(View.VISIBLE); + ((DataViewHolder) holder).subscribeButton.setOnClickListener(view -> { + SubredditSubscription.subscribeToSubreddit(oauthRetrofit, retrofit, + accessToken, accountName, subredditData.getName(), redditDataRoomDatabase, + new SubredditSubscription.SubredditSubscriptionListener() { + @Override + public void onSubredditSubscriptionSuccess() { + ((DataViewHolder) holder).subscribeButton.setVisibility(View.GONE); + Toast.makeText(context, R.string.subscribed, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onSubredditSubscriptionFail() { + Toast.makeText(context, R.string.subscribe_failed, Toast.LENGTH_SHORT).show(); + } + }); + }); + } + }).execute(); + } + } + + @Override + public int getItemViewType(int position) { + // Reached at the end + if (hasExtraRow() && position == getItemCount() - 1) { + if (networkState.getStatus() == NetworkState.Status.LOADING) { + return VIEW_TYPE_LOADING; + } else { + return VIEW_TYPE_ERROR; + } + } else { + return VIEW_TYPE_DATA; + } + } + + @Override + public int getItemCount() { + if(hasExtraRow()) { + return super.getItemCount() + 1; + } + return super.getItemCount(); + } + + private boolean hasExtraRow() { + return networkState != null && networkState.getStatus() != NetworkState.Status.SUCCESS; + } + + public void setNetworkState(NetworkState newNetworkState) { + NetworkState previousState = this.networkState; + boolean previousExtraRow = hasExtraRow(); + this.networkState = newNetworkState; + boolean newExtraRow = hasExtraRow(); + if (previousExtraRow != newExtraRow) { + if (previousExtraRow) { + notifyItemRemoved(super.getItemCount()); + } else { + notifyItemInserted(super.getItemCount()); + } + } else if (newExtraRow && !previousState.equals(newNetworkState)) { + notifyItemChanged(getItemCount() - 1); + } + } + + class DataViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.constraint_layout_item_subreddit_listing) ConstraintLayout constraintLayout; + @BindView(R.id.subreddit_icon_gif_image_view_item_subreddit_listing) GifImageView iconGifImageView; + @BindView(R.id.subreddit_name_text_view_item_subreddit_listing) TextView subredditNameTextView; + @BindView(R.id.subscribe_image_view_item_subreddit_listing) ImageView subscribeButton; + + DataViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + } + + class ErrorViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.error_text_view_item_footer_error) TextView errorTextView; + @BindView(R.id.retry_button_item_footer_error) Button retryButton; + + ErrorViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + retryButton.setOnClickListener(view -> callback.retryLoadingMore()); + errorTextView.setText(R.string.load_comments_failed); + } + } + + class LoadingViewHolder extends RecyclerView.ViewHolder { + LoadingViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + } + + @Override + public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { + if(holder instanceof DataViewHolder) { + glide.clear(((DataViewHolder) holder).iconGifImageView); + ((DataViewHolder) holder).subscribeButton.setVisibility(View.GONE); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/SubscribedSubredditsRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/SubscribedSubredditsRecyclerViewAdapter.java new file mode 100644 index 00000000..4dadc468 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/SubscribedSubredditsRecyclerViewAdapter.java @@ -0,0 +1,154 @@ +package ml.docilealligator.infinityforreddit.Adapter; + +import android.content.Context; +import android.content.Intent; +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 com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.request.RequestOptions; + +import java.util.List; + +import ml.docilealligator.infinityforreddit.Activity.ViewSubredditDetailActivity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditData; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import pl.droidsonroids.gif.GifImageView; + +public class SubscribedSubredditsRecyclerViewAdapter extends RecyclerView.Adapter { + private Context mContext; + private List mSubscribedSubredditData; + private RequestManager glide; + private ItemClickListener itemClickListener; + + private String username; + private String userIconUrl; + private boolean hasClearSelectionRow; + + public interface ItemClickListener { + void onClick(String name, String iconUrl, boolean subredditIsUser); + } + + public SubscribedSubredditsRecyclerViewAdapter(Context context) { + mContext = context; + glide = Glide.with(context.getApplicationContext()); + } + + public SubscribedSubredditsRecyclerViewAdapter(Context context, boolean hasClearSelectionRow, ItemClickListener itemClickListener) { + mContext = context; + this.hasClearSelectionRow = hasClearSelectionRow; + glide = Glide.with(context.getApplicationContext()); + this.itemClickListener = itemClickListener; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { + return new SubredditViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_subscribed_thing, viewGroup, false)); + } + + @Override + public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, final int i) { + String name; + String iconUrl; + + if(itemClickListener != null) { + if(hasClearSelectionRow) { + if(viewHolder.getAdapterPosition() == 0) { + ((SubredditViewHolder) viewHolder).subredditNameTextView.setText(R.string.all_subreddits); + viewHolder.itemView.setOnClickListener(view -> itemClickListener.onClick(null, null, false)); + return; + } else if(viewHolder.getAdapterPosition() == 1) { + name = username; + iconUrl = userIconUrl; + viewHolder.itemView.setOnClickListener(view -> itemClickListener.onClick(name, iconUrl, true)); + } else { + name = mSubscribedSubredditData.get(viewHolder.getAdapterPosition() - 2).getName(); + iconUrl = mSubscribedSubredditData.get(viewHolder.getAdapterPosition() - 2).getIconUrl(); + viewHolder.itemView.setOnClickListener(view -> itemClickListener.onClick(name, iconUrl, false)); + } + } else { + if(viewHolder.getAdapterPosition() == 0) { + name = username; + iconUrl = userIconUrl; + viewHolder.itemView.setOnClickListener(view -> itemClickListener.onClick(name, iconUrl, true)); + } else { + name = mSubscribedSubredditData.get(viewHolder.getAdapterPosition() - 1).getName(); + iconUrl = mSubscribedSubredditData.get(viewHolder.getAdapterPosition() - 1).getIconUrl(); + viewHolder.itemView.setOnClickListener(view -> itemClickListener.onClick(name, iconUrl, false)); + } + } + } else { + name = mSubscribedSubredditData.get(viewHolder.getAdapterPosition()).getName(); + iconUrl = mSubscribedSubredditData.get(viewHolder.getAdapterPosition()).getIconUrl(); + + viewHolder.itemView.setOnClickListener(view -> { + Intent intent = new Intent(mContext, ViewSubredditDetailActivity.class); + intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, name); + mContext.startActivity(intent); + }); + } + + if(iconUrl != null && !iconUrl.equals("")) { + glide.load(iconUrl) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(glide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((SubredditViewHolder) viewHolder).iconGifImageView); + } else { + glide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((SubredditViewHolder) viewHolder).iconGifImageView); + } + ((SubredditViewHolder) viewHolder).subredditNameTextView.setText(name); + } + + @Override + public int getItemCount() { + if(mSubscribedSubredditData != null) { + if(itemClickListener != null) { + if(hasClearSelectionRow) { + return mSubscribedSubredditData.size() + 2; + } else { + return mSubscribedSubredditData.size() + 1; + } + } + + return mSubscribedSubredditData.size(); + } + return 0; + } + + @Override + public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { + glide.clear(((SubredditViewHolder) holder).iconGifImageView); + } + + public void setSubscribedSubreddits(List subscribedSubreddits){ + mSubscribedSubredditData = subscribedSubreddits; + notifyDataSetChanged(); + } + + public void addUser(String username, String userIconUrl) { + this.username = username; + this.userIconUrl = userIconUrl; + } + + private class SubredditViewHolder extends RecyclerView.ViewHolder { + private final GifImageView iconGifImageView; + private final TextView subredditNameTextView; + + SubredditViewHolder(View itemView) { + super(itemView); + iconGifImageView = itemView.findViewById(R.id.subreddit_icon_gif_image_view_item_subscribed_subreddit); + subredditNameTextView = itemView.findViewById(R.id.subreddit_name_text_view_item_subscribed_subreddit); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/UserListingRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/UserListingRecyclerViewAdapter.java new file mode 100644 index 00000000..3cdf03c9 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/UserListingRecyclerViewAdapter.java @@ -0,0 +1,234 @@ +package ml.docilealligator.infinityforreddit.Adapter; + +import android.content.Context; +import android.content.Intent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.paging.PagedListAdapter; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.request.RequestOptions; + +import ml.docilealligator.infinityforreddit.Activity.ViewUserDetailActivity; +import ml.docilealligator.infinityforreddit.AsyncTask.CheckIsFollowingUserAsyncTask; +import ml.docilealligator.infinityforreddit.NetworkState; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserDao; +import ml.docilealligator.infinityforreddit.User.UserData; +import butterknife.BindView; +import butterknife.ButterKnife; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import ml.docilealligator.infinityforreddit.UserFollowing; +import pl.droidsonroids.gif.GifImageView; +import retrofit2.Retrofit; + +public class UserListingRecyclerViewAdapter extends PagedListAdapter { + public interface RetryLoadingMoreCallback { + void retryLoadingMore(); + } + + private RequestManager glide; + + private static final int VIEW_TYPE_DATA = 0; + private static final int VIEW_TYPE_ERROR = 1; + private static final int VIEW_TYPE_LOADING = 2; + + private Context context; + private Retrofit oauthRetrofit; + private Retrofit retrofit; + private String accessToken; + private String accountName; + private SubscribedUserDao subscribedUserDao; + + private NetworkState networkState; + private UserListingRecyclerViewAdapter.RetryLoadingMoreCallback retryLoadingMoreCallback; + + public UserListingRecyclerViewAdapter(Context context, Retrofit oauthRetrofit, Retrofit retrofit, + String accessToken, String accountName, SubscribedUserDao subscribedUserDao, + UserListingRecyclerViewAdapter.RetryLoadingMoreCallback retryLoadingMoreCallback) { + super(DIFF_CALLBACK); + this.context = context; + this.oauthRetrofit = oauthRetrofit; + this.retrofit = retrofit; + this.accessToken = accessToken; + this.accountName = accountName; + this.subscribedUserDao = subscribedUserDao; + this.retryLoadingMoreCallback = retryLoadingMoreCallback; + glide = Glide.with(context.getApplicationContext()); + } + + private static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() { + @Override + public boolean areItemsTheSame(@NonNull UserData oldItem, @NonNull UserData newItem) { + return oldItem.getName().equals(newItem.getName()); + } + + @Override + public boolean areContentsTheSame(@NonNull UserData oldItem, @NonNull UserData newItem) { + return true; + } + }; + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + if(viewType == VIEW_TYPE_DATA) { + ConstraintLayout constraintLayout = (ConstraintLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_user_listing, parent, false); + return new UserListingRecyclerViewAdapter.DataViewHolder(constraintLayout); + } else if(viewType == VIEW_TYPE_ERROR) { + RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_error, parent, false); + return new UserListingRecyclerViewAdapter.ErrorViewHolder(relativeLayout); + } else { + RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_loading, parent, false); + return new UserListingRecyclerViewAdapter.LoadingViewHolder(relativeLayout); + } + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if(holder instanceof UserListingRecyclerViewAdapter.DataViewHolder) { + UserData userData = getItem(position); + ((UserListingRecyclerViewAdapter.DataViewHolder) holder).constraintLayout.setOnClickListener(view -> { + Intent intent = new Intent(context, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, userData.getName()); + context.startActivity(intent); + }); + + if(!userData.getIconUrl().equals("")) { + glide.load(userData.getIconUrl()) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(glide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((UserListingRecyclerViewAdapter.DataViewHolder) holder).iconGifImageView); + } else { + glide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((UserListingRecyclerViewAdapter.DataViewHolder) holder).iconGifImageView); + } + + ((UserListingRecyclerViewAdapter.DataViewHolder) holder).UserNameTextView.setText(userData.getName()); + + new CheckIsFollowingUserAsyncTask(subscribedUserDao, userData.getName(), accountName, + new CheckIsFollowingUserAsyncTask.CheckIsFollowingUserListener() { + @Override + public void isSubscribed() { + ((UserListingRecyclerViewAdapter.DataViewHolder) holder).subscribeButton.setVisibility(View.GONE); + } + + @Override + public void isNotSubscribed() { + ((UserListingRecyclerViewAdapter.DataViewHolder) holder).subscribeButton.setVisibility(View.VISIBLE); + ((UserListingRecyclerViewAdapter.DataViewHolder) holder).subscribeButton.setOnClickListener(view -> { + UserFollowing.followUser(oauthRetrofit, retrofit, + accessToken, userData.getName(), accountName, subscribedUserDao, + new UserFollowing.UserFollowingListener() { + @Override + public void onUserFollowingSuccess() { + ((UserListingRecyclerViewAdapter.DataViewHolder) holder).subscribeButton.setVisibility(View.GONE); + Toast.makeText(context, R.string.followed, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onUserFollowingFail() { + Toast.makeText(context, R.string.follow_failed, Toast.LENGTH_SHORT).show(); + } + }); + }); + } + }).execute(); + } + } + + @Override + public int getItemViewType(int position) { + // Reached at the end + if (hasExtraRow() && position == getItemCount() - 1) { + if (networkState.getStatus() == NetworkState.Status.LOADING) { + return VIEW_TYPE_LOADING; + } else { + return VIEW_TYPE_ERROR; + } + } else { + return VIEW_TYPE_DATA; + } + } + + @Override + public int getItemCount() { + if(hasExtraRow()) { + return super.getItemCount() + 1; + } + return super.getItemCount(); + } + + private boolean hasExtraRow() { + return networkState != null && networkState.getStatus() != NetworkState.Status.SUCCESS; + } + + public void setNetworkState(NetworkState newNetworkState) { + NetworkState previousState = this.networkState; + boolean previousExtraRow = hasExtraRow(); + this.networkState = newNetworkState; + boolean newExtraRow = hasExtraRow(); + if (previousExtraRow != newExtraRow) { + if (previousExtraRow) { + notifyItemRemoved(super.getItemCount()); + } else { + notifyItemInserted(super.getItemCount()); + } + } else if (newExtraRow && !previousState.equals(newNetworkState)) { + notifyItemChanged(getItemCount() - 1); + } + } + + class DataViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.constraint_layout_item_user_listing) ConstraintLayout constraintLayout; + @BindView(R.id.user_icon_gif_image_view_item_user_listing) GifImageView iconGifImageView; + @BindView(R.id.user_name_text_view_item_user_listing) TextView UserNameTextView; + @BindView(R.id.subscribe_image_view_item_user_listing) ImageView subscribeButton; + + DataViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + } + + class ErrorViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.error_text_view_item_footer_error) TextView errorTextView; + @BindView(R.id.retry_button_item_footer_error) Button retryButton; + + ErrorViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + retryButton.setOnClickListener(view -> retryLoadingMoreCallback.retryLoadingMore()); + errorTextView.setText(R.string.load_comments_failed); + } + } + + class LoadingViewHolder extends RecyclerView.ViewHolder { + LoadingViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + } + + @Override + public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { + if(holder instanceof UserListingRecyclerViewAdapter.DataViewHolder) { + glide.clear(((UserListingRecyclerViewAdapter.DataViewHolder) holder).iconGifImageView); + ((UserListingRecyclerViewAdapter.DataViewHolder) holder).subscribeButton.setVisibility(View.GONE); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AppBarStateChangeListener.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AppBarStateChangeListener.java index dcb034bf..56922cb1 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/AppBarStateChangeListener.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AppBarStateChangeListener.java @@ -2,7 +2,7 @@ package ml.docilealligator.infinityforreddit; import com.google.android.material.appbar.AppBarLayout; -abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener { +public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener { // State public enum State { EXPANDED, @@ -37,5 +37,5 @@ abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChanged * @param appBarLayout Layout * @param state Collapse state */ - abstract void onStateChanged(AppBarLayout appBarLayout, AppBarStateChangeListener.State state); + public abstract void onStateChanged(AppBarLayout appBarLayout, AppBarStateChangeListener.State state); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java index 0dffadd8..d1009faa 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java @@ -2,6 +2,38 @@ package ml.docilealligator.infinityforreddit; import javax.inject.Singleton; +import ml.docilealligator.infinityforreddit.Activity.AccountPostsActivity; +import ml.docilealligator.infinityforreddit.Activity.AccountSavedThingActivity; +import ml.docilealligator.infinityforreddit.Activity.CommentActivity; +import ml.docilealligator.infinityforreddit.Activity.EditCommentActivity; +import ml.docilealligator.infinityforreddit.Activity.EditPostActivity; +import ml.docilealligator.infinityforreddit.Activity.FilteredThingActivity; +import ml.docilealligator.infinityforreddit.Activity.LinkResolverActivity; +import ml.docilealligator.infinityforreddit.Activity.LoginActivity; +import ml.docilealligator.infinityforreddit.Activity.MainActivity; +import ml.docilealligator.infinityforreddit.Activity.PostImageActivity; +import ml.docilealligator.infinityforreddit.Activity.PostLinkActivity; +import ml.docilealligator.infinityforreddit.Activity.PostTextActivity; +import ml.docilealligator.infinityforreddit.Activity.PostVideoActivity; +import ml.docilealligator.infinityforreddit.Activity.RulesActivity; +import ml.docilealligator.infinityforreddit.Activity.SearchActivity; +import ml.docilealligator.infinityforreddit.Activity.SearchResultActivity; +import ml.docilealligator.infinityforreddit.Activity.SearchSubredditsResultActivity; +import ml.docilealligator.infinityforreddit.Activity.SettingsActivity; +import ml.docilealligator.infinityforreddit.Activity.SubredditSelectionActivity; +import ml.docilealligator.infinityforreddit.Activity.SubscribedThingListingActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewImageActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewMessageActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewPostDetailActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewSubredditDetailActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewUserDetailActivity; +import ml.docilealligator.infinityforreddit.Fragment.CommentsListingFragment; +import ml.docilealligator.infinityforreddit.Fragment.FlairBottomSheetFragment; +import ml.docilealligator.infinityforreddit.Fragment.FollowedUsersListingFragment; +import ml.docilealligator.infinityforreddit.Fragment.PostFragment; +import ml.docilealligator.infinityforreddit.Fragment.SubredditListingFragment; +import ml.docilealligator.infinityforreddit.Fragment.SubscribedSubredditsListingFragment; +import ml.docilealligator.infinityforreddit.Fragment.UserListingFragment; import ml.docilealligator.infinityforreddit.Settings.MainPreferenceFragment; import ml.docilealligator.infinityforreddit.Settings.NotificationPreferenceFragment; import dagger.Component; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/CheckIsFollowingUserAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/CheckIsFollowingUserAsyncTask.java new file mode 100644 index 00000000..17c0f676 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/CheckIsFollowingUserAsyncTask.java @@ -0,0 +1,43 @@ +package ml.docilealligator.infinityforreddit.AsyncTask; + +import android.os.AsyncTask; + +import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserDao; +import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserData; + +public class CheckIsFollowingUserAsyncTask extends AsyncTask { + private SubscribedUserDao subscribedUserDao; + private String username; + private String accountName; + private SubscribedUserData subscribedUserData; + private CheckIsFollowingUserListener checkIsFollowingUserListener; + + public interface CheckIsFollowingUserListener { + void isSubscribed(); + void isNotSubscribed(); + } + + public CheckIsFollowingUserAsyncTask(SubscribedUserDao subscribedUserDao, String username, String accountName, + CheckIsFollowingUserListener checkIsFollowingUserListener) { + this.subscribedUserDao = subscribedUserDao; + this.username = username; + this.accountName = accountName; + this.checkIsFollowingUserListener = checkIsFollowingUserListener; + } + + @Override + protected Void doInBackground(Void... voids) { + subscribedUserData = subscribedUserDao.getSubscribedUser(username, accountName); + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + if(subscribedUserData != null) { + checkIsFollowingUserListener.isSubscribed(); + } else { + checkIsFollowingUserListener.isNotSubscribed(); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/CheckIsSubscribedToSubredditAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/CheckIsSubscribedToSubredditAsyncTask.java new file mode 100644 index 00000000..0ea76144 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/CheckIsSubscribedToSubredditAsyncTask.java @@ -0,0 +1,45 @@ +package ml.docilealligator.infinityforreddit.AsyncTask; + +import android.os.AsyncTask; + +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditData; + +public class CheckIsSubscribedToSubredditAsyncTask extends AsyncTask { + + private RedditDataRoomDatabase redditDataRoomDatabase; + private String subredditName; + private String accountName; + private SubscribedSubredditData subscribedSubredditData; + private CheckIsSubscribedToSubredditListener checkIsSubscribedToSubredditListener; + + public interface CheckIsSubscribedToSubredditListener { + void isSubscribed(); + void isNotSubscribed(); + } + + public CheckIsSubscribedToSubredditAsyncTask(RedditDataRoomDatabase redditDataRoomDatabase, + String subredditName, String accountName, + CheckIsSubscribedToSubredditListener checkIsSubscribedToSubredditListener) { + this.redditDataRoomDatabase = redditDataRoomDatabase; + this.subredditName =subredditName; + this.accountName = accountName; + this.checkIsSubscribedToSubredditListener = checkIsSubscribedToSubredditListener; + } + + @Override + protected Void doInBackground(Void... voids) { + subscribedSubredditData = redditDataRoomDatabase.subscribedSubredditDao().getSubscribedSubreddit(subredditName, accountName); + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + if(subscribedSubredditData != null) { + checkIsSubscribedToSubredditListener.isSubscribed(); + } else { + checkIsSubscribedToSubredditListener.isNotSubscribed(); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/GetCurrentAccountAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/GetCurrentAccountAsyncTask.java new file mode 100644 index 00000000..b54fa104 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/GetCurrentAccountAsyncTask.java @@ -0,0 +1,33 @@ +package ml.docilealligator.infinityforreddit.AsyncTask; + +import android.os.AsyncTask; + +import ml.docilealligator.infinityforreddit.Account.Account; +import ml.docilealligator.infinityforreddit.Account.AccountDao; + +public class GetCurrentAccountAsyncTask extends AsyncTask { + + public interface GetCurrentAccountAsyncTaskListener { + void success(Account account); + } + + Account account; + AccountDao accountDao; + GetCurrentAccountAsyncTaskListener getCurrentAccountAsyncTaskListener; + + public GetCurrentAccountAsyncTask(AccountDao accountDao, GetCurrentAccountAsyncTaskListener getCurrentAccountAsyncTaskListener) { + this.accountDao = accountDao; + this.getCurrentAccountAsyncTaskListener = getCurrentAccountAsyncTaskListener; + } + + @Override + protected Void doInBackground(Void... voids) { + account = accountDao.getCurrentAccount(); + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + getCurrentAccountAsyncTaskListener.success(account); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/InsertSubscribedThingsAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/InsertSubscribedThingsAsyncTask.java new file mode 100644 index 00000000..ac4490fa --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/InsertSubscribedThingsAsyncTask.java @@ -0,0 +1,80 @@ +package ml.docilealligator.infinityforreddit.AsyncTask; + +import android.os.AsyncTask; + +import androidx.annotation.Nullable; + +import java.util.List; + +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditDao; +import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditData; +import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditDao; +import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditData; +import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserDao; +import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserData; + +public class InsertSubscribedThingsAsyncTask extends AsyncTask { + + public interface InsertSubscribedThingListener { + void insertSuccess(); + } + + private RedditDataRoomDatabase mRedditDataRoomDatabase; + private String mAccountName; + private SubscribedSubredditDao mSubscribedSubredditDao; + private SubscribedUserDao mUserDao; + private SubredditDao mSubredditDao; + private List subscribedSubredditData; + private List subscribedUserData; + private List subredditData; + private InsertSubscribedThingListener insertSubscribedThingListener; + + public InsertSubscribedThingsAsyncTask(RedditDataRoomDatabase redditDataRoomDatabase, @Nullable String accountName, + List subscribedSubredditData, + List subscribedUserData, + List subredditData, + InsertSubscribedThingListener insertSubscribedThingListener) { + mRedditDataRoomDatabase = redditDataRoomDatabase; + mAccountName = accountName; + mSubscribedSubredditDao = redditDataRoomDatabase.subscribedSubredditDao(); + mUserDao = redditDataRoomDatabase.subscribedUserDao(); + mSubredditDao = redditDataRoomDatabase.subredditDao(); + + this.subscribedSubredditData = subscribedSubredditData; + this.subscribedUserData = subscribedUserData; + this.subredditData = subredditData; + this.insertSubscribedThingListener = insertSubscribedThingListener; + } + + @Override + protected Void doInBackground(final Void... params) { + if(mAccountName != null && mRedditDataRoomDatabase.accountDao().getAccountData(mAccountName) == null) { + return null; + } + + if(subscribedSubredditData != null) { + for (SubscribedSubredditData s : subscribedSubredditData) { + mSubscribedSubredditDao.insert(s); + } + } + + if(subscribedUserData != null) { + for (SubscribedUserData s : subscribedUserData) { + mUserDao.insert(s); + } + } + + if(subredditData != null) { + for (SubredditData s : subredditData) { + mSubredditDao.insert(s); + } + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + insertSubscribedThingListener.insertSuccess(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/InsertUserDataAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/InsertUserDataAsyncTask.java new file mode 100644 index 00000000..949276e0 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/InsertUserDataAsyncTask.java @@ -0,0 +1,36 @@ +package ml.docilealligator.infinityforreddit.AsyncTask; + +import android.os.AsyncTask; + +import ml.docilealligator.infinityforreddit.User.UserData; +import ml.docilealligator.infinityforreddit.User.UserDao; + +public class InsertUserDataAsyncTask extends AsyncTask { + private UserDao userDao; + private UserData userData; + private InsertUserDataCallback insertUserDataCallback; + + public interface InsertUserDataCallback { + void insertSuccess(); + } + + public InsertUserDataAsyncTask(UserDao userDao, UserData userData, InsertUserDataCallback insertUserDataCallback) { + this.userDao = userDao; + this.userData = userData; + this.insertUserDataCallback = insertUserDataCallback; + } + + @Override + protected Void doInBackground(Void... voids) { + userDao.insert(userData); + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + if(insertUserDataCallback != null) { + insertUserDataCallback.insertSuccess(); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/LoadSubredditIconAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/LoadSubredditIconAsyncTask.java new file mode 100644 index 00000000..2acc6bf5 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/LoadSubredditIconAsyncTask.java @@ -0,0 +1,72 @@ +package ml.docilealligator.infinityforreddit.AsyncTask; + +import android.os.AsyncTask; + +import java.util.ArrayList; + +import ml.docilealligator.infinityforreddit.FetchSubredditData; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditDao; +import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditData; +import retrofit2.Retrofit; + +public class LoadSubredditIconAsyncTask extends AsyncTask { + public interface LoadSubredditIconAsyncTaskListener { + void loadIconSuccess(String iconImageUrl); + } + + private RedditDataRoomDatabase redditDataRoomDatabase; + private SubredditDao subredditDao; + private String subredditName; + private Retrofit retrofit; + private String iconImageUrl; + private boolean hasSubredditInDb; + private LoadSubredditIconAsyncTaskListener loadSubredditIconAsyncTaskListener; + + public LoadSubredditIconAsyncTask(RedditDataRoomDatabase redditDataRoomDatabase, String subredditName, Retrofit retrofit, + LoadSubredditIconAsyncTaskListener loadSubredditIconAsyncTaskListener) { + this.redditDataRoomDatabase = redditDataRoomDatabase; + this.subredditDao = redditDataRoomDatabase.subredditDao(); + this.subredditName = subredditName; + this.retrofit = retrofit; + this.loadSubredditIconAsyncTaskListener = loadSubredditIconAsyncTaskListener; + } + + @Override + protected Void doInBackground(Void... voids) { + SubredditData subredditData = subredditDao.getSubredditData(subredditName); + if(subredditData != null) { + iconImageUrl = subredditDao.getSubredditData(subredditName).getIconUrl(); + hasSubredditInDb = true; + } else { + hasSubredditInDb = false; + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + if(!isCancelled()) { + if(hasSubredditInDb) { + loadSubredditIconAsyncTaskListener.loadIconSuccess(iconImageUrl); + } else { + FetchSubredditData.fetchSubredditData(retrofit, subredditName, new FetchSubredditData.FetchSubredditDataListener() { + @Override + public void onFetchSubredditDataSuccess(SubredditData subredditData, int nCurrentOnlineSubscribers) { + ArrayList singleSubredditDataList = new ArrayList<>(); + singleSubredditDataList.add(subredditData); + new InsertSubscribedThingsAsyncTask(redditDataRoomDatabase, null, + null, null, singleSubredditDataList, + () -> loadSubredditIconAsyncTaskListener.loadIconSuccess(subredditData.getIconUrl())).execute(); + } + + @Override + public void onFetchSubredditDataFail() { + loadSubredditIconAsyncTaskListener.loadIconSuccess(null); + } + }); + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/LoadUserDataAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/LoadUserDataAsyncTask.java new file mode 100644 index 00000000..e67ef190 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/LoadUserDataAsyncTask.java @@ -0,0 +1,59 @@ +package ml.docilealligator.infinityforreddit.AsyncTask; + +import android.os.AsyncTask; + +import ml.docilealligator.infinityforreddit.FetchUserData; +import ml.docilealligator.infinityforreddit.User.UserData; +import ml.docilealligator.infinityforreddit.User.UserDao; +import retrofit2.Retrofit; + +public class LoadUserDataAsyncTask extends AsyncTask { + public interface LoadUserDataAsyncTaskListener { + void loadUserDataSuccess(String iconImageUrl); + } + + private UserDao userDao; + private String userName; + private String iconImageUrl; + private boolean hasUserInDb; + private Retrofit retrofit; + private LoadUserDataAsyncTaskListener loadUserDataAsyncTaskListener; + + public LoadUserDataAsyncTask(UserDao userDao, String userName, Retrofit retrofit, LoadUserDataAsyncTaskListener loadUserDataAsyncTaskListener) { + this.userDao = userDao; + this.userName = userName; + this.retrofit = retrofit; + this.loadUserDataAsyncTaskListener = loadUserDataAsyncTaskListener; + } + + @Override + protected Void doInBackground(Void... voids) { + if(userDao.getUserData(userName) != null) { + iconImageUrl = userDao.getUserData(userName).getIconUrl(); + hasUserInDb = true; + } else { + hasUserInDb = false; + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + if(hasUserInDb) { + loadUserDataAsyncTaskListener.loadUserDataSuccess(iconImageUrl); + } else { + FetchUserData.fetchUserData(retrofit, userName, new FetchUserData.FetchUserDataListener() { + @Override + public void onFetchUserDataSuccess(UserData userData) { + new InsertUserDataAsyncTask(userDao, userData, () -> loadUserDataAsyncTaskListener.loadUserDataSuccess(userData.getIconUrl())).execute(); + } + + @Override + public void onFetchUserDataFailed() { + loadUserDataAsyncTaskListener.loadUserDataSuccess(null); + } + }); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/ParseAndInsertNewAccountAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/ParseAndInsertNewAccountAsyncTask.java new file mode 100644 index 00000000..32d801d7 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/ParseAndInsertNewAccountAsyncTask.java @@ -0,0 +1,51 @@ +package ml.docilealligator.infinityforreddit.AsyncTask; + +import android.os.AsyncTask; + +import ml.docilealligator.infinityforreddit.Account.Account; +import ml.docilealligator.infinityforreddit.Account.AccountDao; + +public class ParseAndInsertNewAccountAsyncTask extends AsyncTask { + + public interface ParseAndInsertAccountListener { + void success(); + } + + private String username; + private String accessToken; + private String refreshToken; + private String profileImageUrl; + private String bannerImageUrl; + private int karma; + private String code; + private AccountDao accountDao; + private ParseAndInsertAccountListener parseAndInsertAccountListener; + + public ParseAndInsertNewAccountAsyncTask(String username, String accessToken, String refreshToken, String profileImageUrl, String bannerImageUrl, + int karma, String code, AccountDao accountDao, + ParseAndInsertAccountListener parseAndInsertAccountListener) { + this.username = username; + this.accessToken = accessToken; + this.refreshToken = refreshToken; + this.profileImageUrl = profileImageUrl; + this.bannerImageUrl = bannerImageUrl; + this.karma = karma; + this.code = code; + this.accountDao = accountDao; + this.parseAndInsertAccountListener = parseAndInsertAccountListener; + } + + @Override + protected Void doInBackground(Void... voids) { + Account account = new Account(username, accessToken, refreshToken, code, profileImageUrl, + bannerImageUrl, karma, true); + accountDao.markAllAccountsNonCurrent(); + accountDao.insert(account); + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + parseAndInsertAccountListener.success(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/SwitchAccountAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/SwitchAccountAsyncTask.java new file mode 100644 index 00000000..7b501bbc --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/SwitchAccountAsyncTask.java @@ -0,0 +1,37 @@ +package ml.docilealligator.infinityforreddit.AsyncTask; + +import android.os.AsyncTask; + +import ml.docilealligator.infinityforreddit.Account.Account; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; + +public class SwitchAccountAsyncTask extends AsyncTask { + public interface SwitchAccountAsyncTaskListener { + void switched(Account account); + } + + private RedditDataRoomDatabase redditDataRoomDatabase; + private String newAccountName; + private Account account; + private SwitchAccountAsyncTaskListener switchAccountAsyncTaskListener; + + public SwitchAccountAsyncTask(RedditDataRoomDatabase redditDataRoomDatabase, String newAccountName, + SwitchAccountAsyncTaskListener switchAccountAsyncTaskListener) { + this.redditDataRoomDatabase = redditDataRoomDatabase; + this.newAccountName = newAccountName; + this.switchAccountAsyncTaskListener = switchAccountAsyncTaskListener; + } + + @Override + protected Void doInBackground(Void... voids) { + redditDataRoomDatabase.accountDao().markAllAccountsNonCurrent(); + redditDataRoomDatabase.accountDao().markAccountCurrent(newAccountName); + account = redditDataRoomDatabase.accountDao().getCurrentAccount(); + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + switchAccountAsyncTaskListener.switched(account); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/SwitchToAnonymousAccountAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/SwitchToAnonymousAccountAsyncTask.java new file mode 100644 index 00000000..da141ca5 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/SwitchToAnonymousAccountAsyncTask.java @@ -0,0 +1,38 @@ +package ml.docilealligator.infinityforreddit.AsyncTask; + +import android.os.AsyncTask; + +import ml.docilealligator.infinityforreddit.Account.AccountDao; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; + +public class SwitchToAnonymousAccountAsyncTask extends AsyncTask { + public interface SwitchToAnonymousAccountAsyncTaskListener { + void logoutSuccess(); + } + + private RedditDataRoomDatabase redditDataRoomDatabase; + private boolean removeCurrentAccount; + private SwitchToAnonymousAccountAsyncTaskListener switchToAnonymousAccountAsyncTaskListener; + + public SwitchToAnonymousAccountAsyncTask(RedditDataRoomDatabase redditDataRoomDatabase, boolean removeCurrentAccount, + SwitchToAnonymousAccountAsyncTaskListener switchToAnonymousAccountAsyncTaskListener) { + this.redditDataRoomDatabase = redditDataRoomDatabase; + this.removeCurrentAccount = removeCurrentAccount; + this.switchToAnonymousAccountAsyncTaskListener = switchToAnonymousAccountAsyncTaskListener; + } + + @Override + protected Void doInBackground(Void... voids) { + AccountDao accountDao = redditDataRoomDatabase.accountDao(); + if(removeCurrentAccount) { + accountDao.deleteCurrentAccount(); + } + accountDao.markAllAccountsNonCurrent(); + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + switchToAnonymousAccountAsyncTaskListener.logoutSuccess(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ChangeFontSizeEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ChangeFontSizeEvent.java deleted file mode 100644 index 434ff7a4..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ChangeFontSizeEvent.java +++ /dev/null @@ -1,3 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -public class ChangeFontSizeEvent { } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ChangeNSFWBlurEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ChangeNSFWBlurEvent.java deleted file mode 100644 index 506c1627..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ChangeNSFWBlurEvent.java +++ /dev/null @@ -1,8 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -public class ChangeNSFWBlurEvent { - public boolean needBlurNSFW; - public ChangeNSFWBlurEvent(boolean needBlurNSFW) { - this.needBlurNSFW = needBlurNSFW; - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ChangeNSFWEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ChangeNSFWEvent.java deleted file mode 100644 index 5d4b5a5c..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ChangeNSFWEvent.java +++ /dev/null @@ -1,8 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -public class ChangeNSFWEvent { - public boolean nsfw; - public ChangeNSFWEvent(boolean nsfw) { - this.nsfw = nsfw; - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ChangeSpoilerBlurEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ChangeSpoilerBlurEvent.java deleted file mode 100644 index f8c22224..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ChangeSpoilerBlurEvent.java +++ /dev/null @@ -1,8 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -public class ChangeSpoilerBlurEvent { - public boolean needBlurSpoiler; - public ChangeSpoilerBlurEvent(boolean needBlurSpoiler) { - this.needBlurSpoiler = needBlurSpoiler; - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CheckIsFollowingUserAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CheckIsFollowingUserAsyncTask.java deleted file mode 100644 index b823db11..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CheckIsFollowingUserAsyncTask.java +++ /dev/null @@ -1,43 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.AsyncTask; - -import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserDao; -import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserData; - -public class CheckIsFollowingUserAsyncTask extends AsyncTask { - private SubscribedUserDao subscribedUserDao; - private String username; - private String accountName; - private SubscribedUserData subscribedUserData; - private CheckIsFollowingUserListener checkIsFollowingUserListener; - - interface CheckIsFollowingUserListener { - void isSubscribed(); - void isNotSubscribed(); - } - - CheckIsFollowingUserAsyncTask(SubscribedUserDao subscribedUserDao, String username, String accountName, - CheckIsFollowingUserListener checkIsFollowingUserListener) { - this.subscribedUserDao = subscribedUserDao; - this.username = username; - this.accountName = accountName; - this.checkIsFollowingUserListener = checkIsFollowingUserListener; - } - - @Override - protected Void doInBackground(Void... voids) { - subscribedUserData = subscribedUserDao.getSubscribedUser(username, accountName); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - if(subscribedUserData != null) { - checkIsFollowingUserListener.isSubscribed(); - } else { - checkIsFollowingUserListener.isNotSubscribed(); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CheckIsSubscribedToSubredditAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CheckIsSubscribedToSubredditAsyncTask.java deleted file mode 100644 index a1f304e9..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CheckIsSubscribedToSubredditAsyncTask.java +++ /dev/null @@ -1,44 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.AsyncTask; - -import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditData; - -class CheckIsSubscribedToSubredditAsyncTask extends AsyncTask { - - private RedditDataRoomDatabase redditDataRoomDatabase; - private String subredditName; - private String accountName; - private SubscribedSubredditData subscribedSubredditData; - private CheckIsSubscribedToSubredditListener checkIsSubscribedToSubredditListener; - - interface CheckIsSubscribedToSubredditListener { - void isSubscribed(); - void isNotSubscribed(); - } - - CheckIsSubscribedToSubredditAsyncTask(RedditDataRoomDatabase redditDataRoomDatabase, - String subredditName, String accountName, - CheckIsSubscribedToSubredditListener checkIsSubscribedToSubredditListener) { - this.redditDataRoomDatabase = redditDataRoomDatabase; - this.subredditName =subredditName; - this.accountName = accountName; - this.checkIsSubscribedToSubredditListener = checkIsSubscribedToSubredditListener; - } - - @Override - protected Void doInBackground(Void... voids) { - subscribedSubredditData = redditDataRoomDatabase.subscribedSubredditDao().getSubscribedSubreddit(subredditName, accountName); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - if(subscribedSubredditData != null) { - checkIsSubscribedToSubredditListener.isSubscribed(); - } else { - checkIsSubscribedToSubredditListener.isNotSubscribed(); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentActivity.java deleted file mode 100644 index 6c8eb2f0..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentActivity.java +++ /dev/null @@ -1,273 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.text.util.Linkify; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.view.inputmethod.InputMethodManager; -import android.widget.EditText; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.core.content.ContextCompat; - -import com.google.android.material.snackbar.Snackbar; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import io.noties.markwon.AbstractMarkwonPlugin; -import io.noties.markwon.Markwon; -import io.noties.markwon.MarkwonConfiguration; -import io.noties.markwon.linkify.LinkifyPlugin; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class CommentActivity extends AppCompatActivity { - - static final String EXTRA_COMMENT_PARENT_TEXT_KEY = "ECPTK"; - static final String EXTRA_PARENT_FULLNAME_KEY = "EPFK"; - static final String EXTRA_COMMENT_DATA_KEY = "ECDK"; - static final String EXTRA_PARENT_DEPTH_KEY = "EPDK"; - static final String EXTRA_PARENT_POSITION_KEY = "EPPK"; - static final String EXTRA_IS_REPLYING_KEY = "EIRK"; - static final int WRITE_COMMENT_REQUEST_CODE = 1; - - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - - @BindView(R.id.coordinator_layout_comment_activity) CoordinatorLayout coordinatorLayout; - @BindView(R.id.toolbar_comment_activity) Toolbar toolbar; - @BindView(R.id.comment_parent_markwon_view_comment_activity) TextView commentParentMarkwonView; - @BindView(R.id.comment_edit_text_comment_activity) EditText commentEditText; - - private boolean mNullAccessToken = false; - private String mAccessToken; - private String parentFullname; - private int parentDepth; - private int parentPosition; - private boolean isReplying; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_comment); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - Window window = getWindow(); - if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - if(savedInstanceState == null) { - getCurrentAccount(); - } else { - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - if(!mNullAccessToken && mAccessToken == null) { - getCurrentAccount(); - } - } - - Intent intent = getIntent(); - Markwon markwon = Markwon.builder(this) - .usePlugin(new AbstractMarkwonPlugin() { - @Override - public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { - builder.linkResolver((view, link) -> { - Intent intent = new Intent(CommentActivity.this, LinkResolverActivity.class); - Uri uri = Uri.parse(link); - if(uri.getScheme() == null && uri.getHost() == null) { - intent.setData(LinkResolverActivity.getRedditUriByPath(link)); - } else { - intent.setData(uri); - } - startActivity(intent); - }); - } - }) - .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) - .build(); - markwon.setMarkdown(commentParentMarkwonView, intent.getStringExtra(EXTRA_COMMENT_PARENT_TEXT_KEY)); - parentFullname = intent.getStringExtra(EXTRA_PARENT_FULLNAME_KEY); - parentDepth = intent.getExtras().getInt(EXTRA_PARENT_DEPTH_KEY); - parentPosition = intent.getExtras().getInt(EXTRA_PARENT_POSITION_KEY); - isReplying = intent.getExtras().getBoolean(EXTRA_IS_REPLYING_KEY); - if(isReplying) { - toolbar.setTitle(getString(R.string.comment_activity_label_is_replying)); - } - - setSupportActionBar(toolbar); - - commentEditText.requestFocus(); - InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - if(imm != null) { - imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); - } - } - - private void getCurrentAccount() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - } - }).execute(); - } - - @Override - protected void onPause() { - super.onPause(); - InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); - if(imm != null) { - imm.hideSoftInputFromWindow(commentEditText.getWindowToken(), 0); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.comment_activity, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; - case R.id.action_send_comment_activity: - if(commentEditText.getText() == null || commentEditText.getText().toString().equals("")) { - Snackbar.make(coordinatorLayout, R.string.comment_content_required, Snackbar.LENGTH_SHORT).show(); - return true; - } - - item.setEnabled(false); - item.getIcon().setAlpha(130); - Snackbar sendingSnackbar = Snackbar.make(coordinatorLayout, R.string.sending_comment, Snackbar.LENGTH_INDEFINITE); - sendingSnackbar.show(); - - SendComment.sendComment(commentEditText.getText().toString(), parentFullname, parentDepth, - getResources().getConfiguration().locale, mOauthRetrofit, - mAccessToken, - new SendComment.SendCommentListener() { - @Override - public void sendCommentSuccess(CommentData commentData) { - Toast.makeText(CommentActivity.this, R.string.send_comment_success, Toast.LENGTH_SHORT).show(); - Intent returnIntent = new Intent(); - returnIntent.putExtra(EXTRA_COMMENT_DATA_KEY, commentData); - returnIntent.putExtra(EXTRA_PARENT_FULLNAME_KEY, parentFullname); - if(isReplying) { - returnIntent.putExtra(EXTRA_PARENT_POSITION_KEY, parentPosition); - } - setResult(RESULT_OK, returnIntent); - finish(); - } - - @Override - public void sendCommentFailed(@Nullable String errorMessage) { - sendingSnackbar.dismiss(); - item.setEnabled(true); - item.getIcon().setAlpha(255); - - if(errorMessage == null) { - Snackbar.make(coordinatorLayout, R.string.send_comment_failed, Snackbar.LENGTH_SHORT).show(); - } else { - Snackbar.make(coordinatorLayout, errorMessage, Snackbar.LENGTH_SHORT).show(); - } - } - }); - return true; - } - - return false; - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentAndPostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentAndPostRecyclerViewAdapter.java deleted file mode 100644 index 85b4d230..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentAndPostRecyclerViewAdapter.java +++ /dev/null @@ -1,1752 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.app.Activity; -import android.content.ActivityNotFoundException; -import android.content.Intent; -import android.graphics.ColorFilter; -import android.graphics.PorterDuff; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Bundle; -import android.text.util.Linkify; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.RelativeLayout; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import androidx.core.content.ContextCompat; -import androidx.recyclerview.widget.RecyclerView; - -import com.bumptech.glide.RequestBuilder; -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.RequestOptions; -import com.bumptech.glide.request.target.Target; -import com.libRG.CustomTextView; -import com.santalu.aspectratioimageview.AspectRatioImageView; - -import java.util.ArrayList; -import java.util.Locale; - -import ml.docilealligator.infinityforreddit.CustomView.AspectRatioGifImageView; -import butterknife.BindView; -import butterknife.ButterKnife; -import io.noties.markwon.AbstractMarkwonPlugin; -import io.noties.markwon.Markwon; -import io.noties.markwon.MarkwonConfiguration; -import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.linkify.LinkifyPlugin; -import io.noties.markwon.urlprocessor.UrlProcessorRelativeToAbsolute; -import jp.wasabeef.glide.transformations.BlurTransformation; -import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import retrofit2.Retrofit; - -import static ml.docilealligator.infinityforreddit.CommentActivity.WRITE_COMMENT_REQUEST_CODE; - -class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter { - private static final int VIEW_TYPE_POST_DETAIL = 0; - private static final int VIEW_TYPE_FIRST_LOADING = 1; - private static final int VIEW_TYPE_FIRST_LOADING_FAILED = 2; - private static final int VIEW_TYPE_NO_COMMENT_PLACEHOLDER = 3; - private static final int VIEW_TYPE_COMMENT = 4; - private static final int VIEW_TYPE_LOAD_MORE_CHILD_COMMENTS = 5; - private static final int VIEW_TYPE_IS_LOADING_MORE_COMMENTS = 6; - private static final int VIEW_TYPE_LOAD_MORE_COMMENTS_FAILED = 7; - private static final int VIEW_TYPE_VIEW_ALL_COMMENTS = 8; - - private Activity mActivity; - private Retrofit mRetrofit; - private Retrofit mOauthRetrofit; - private RedditDataRoomDatabase mRedditDataRoomDatabase; - private RequestManager mGlide; - private Markwon mMarkwon; - private String mAccessToken; - private String mAccountName; - private Post mPost; - private ArrayList mVisibleComments; - private String mSubredditNamePrefixed; - private Locale mLocale; - private String mSingleCommentId; - private boolean mIsSingleCommentThreadMode; - private boolean mNeedBlurNSFW; - private boolean mNeedBlurSpoiler; - private CommentRecyclerViewAdapterCallback mCommentRecyclerViewAdapterCallback; - private boolean isInitiallyLoading; - private boolean isInitiallyLoadingFailed; - private boolean mHasMoreComments; - private boolean loadMoreCommentsFailed; - - interface CommentRecyclerViewAdapterCallback { - void updatePost(Post post); - void retryFetchingComments(); - void retryFetchingMoreComments(); - } - - CommentAndPostRecyclerViewAdapter(Activity activity, Retrofit retrofit, Retrofit oauthRetrofit, - RedditDataRoomDatabase redditDataRoomDatabase, RequestManager glide, - String accessToken, String accountName, Post post, Locale locale, - String singleCommentId, boolean isSingleCommentThreadMode, - boolean needBlurNSFW, boolean needBlurSpoiler, - CommentRecyclerViewAdapterCallback commentRecyclerViewAdapterCallback) { - mActivity = activity; - mRetrofit = retrofit; - mOauthRetrofit = oauthRetrofit; - mRedditDataRoomDatabase = redditDataRoomDatabase; - mGlide = glide; - mMarkwon = Markwon.builder(mActivity) - .usePlugin(new AbstractMarkwonPlugin() { - @Override - public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { - builder.linkResolver((view, link) -> { - Intent intent = new Intent(mActivity, LinkResolverActivity.class); - Uri uri = Uri.parse(link); - if(uri.getScheme() == null && uri.getHost() == null) { - intent.setData(LinkResolverActivity.getRedditUriByPath(link)); - } else { - intent.setData(uri); - } - mActivity.startActivity(intent); - }).urlProcessor(new UrlProcessorRelativeToAbsolute("https://www.reddit.com")); - } - }) - .usePlugin(StrikethroughPlugin.create()) - .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) - .build(); - mAccessToken = accessToken; - mAccountName = accountName; - mPost = post; - mVisibleComments = new ArrayList<>(); - mSubredditNamePrefixed = post.getSubredditNamePrefixed(); - mLocale = locale; - mSingleCommentId = singleCommentId; - mIsSingleCommentThreadMode = isSingleCommentThreadMode; - mNeedBlurNSFW = needBlurNSFW; - mNeedBlurSpoiler = needBlurSpoiler; - mCommentRecyclerViewAdapterCallback = commentRecyclerViewAdapterCallback; - isInitiallyLoading = true; - isInitiallyLoadingFailed = false; - mHasMoreComments = false; - loadMoreCommentsFailed = false; - } - - @Override - public int getItemViewType(int position) { - if(position == 0) { - return VIEW_TYPE_POST_DETAIL; - } - - if(mVisibleComments.size() == 0) { - if(position == 1) { - if(isInitiallyLoading) { - return VIEW_TYPE_FIRST_LOADING; - } else if(isInitiallyLoadingFailed) { - return VIEW_TYPE_FIRST_LOADING_FAILED; - } else { - return VIEW_TYPE_NO_COMMENT_PLACEHOLDER; - } - } - } - - if(mIsSingleCommentThreadMode) { - if(position == 1) { - return VIEW_TYPE_VIEW_ALL_COMMENTS; - } - - if(position == mVisibleComments.size() + 2) { - if(mHasMoreComments) { - return VIEW_TYPE_IS_LOADING_MORE_COMMENTS; - } else { - return VIEW_TYPE_LOAD_MORE_COMMENTS_FAILED; - } - } - - CommentData comment = mVisibleComments.get(position - 2); - if(!comment.isPlaceHolder()) { - return VIEW_TYPE_COMMENT; - } else { - return VIEW_TYPE_LOAD_MORE_CHILD_COMMENTS; - } - } else { - if(position == mVisibleComments.size() + 1) { - if(mHasMoreComments) { - return VIEW_TYPE_IS_LOADING_MORE_COMMENTS; - } else { - return VIEW_TYPE_LOAD_MORE_COMMENTS_FAILED; - } - } - - CommentData comment = mVisibleComments.get(position - 1); - if(!comment.isPlaceHolder()) { - return VIEW_TYPE_COMMENT; - } else { - return VIEW_TYPE_LOAD_MORE_CHILD_COMMENTS; - } - } - } - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - switch (viewType) { - case VIEW_TYPE_POST_DETAIL: - return new PostDetailViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_post_detail, parent, false)); - case VIEW_TYPE_FIRST_LOADING: - return new LoadCommentsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_comments, parent, false)); - case VIEW_TYPE_FIRST_LOADING_FAILED: - return new LoadCommentsFailedViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_comments_failed_placeholder, parent, false)); - case VIEW_TYPE_NO_COMMENT_PLACEHOLDER: - return new NoCommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_no_comment_placeholder, parent, false)); - case VIEW_TYPE_COMMENT: - return new CommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment, parent, false)); - case VIEW_TYPE_LOAD_MORE_CHILD_COMMENTS: - return new LoadMoreChildCommentsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_load_more_comments_placeholder, parent, false)); - case VIEW_TYPE_IS_LOADING_MORE_COMMENTS: - return new IsLoadingMoreCommentsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment_footer_loading, parent, false)); - case VIEW_TYPE_LOAD_MORE_COMMENTS_FAILED: - return new LoadMoreCommentsFailedViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment_footer_error, parent, false)); - default: - return new ViewAllCommentsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view_all_comments, parent, false)); - } - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - if(holder.getItemViewType() == VIEW_TYPE_POST_DETAIL) { - ((PostDetailViewHolder) holder).mTitleTextView.setText(mPost.getTitle()); - if(mPost.getSubredditNamePrefixed().startsWith("u/")) { - if(mPost.getAuthorIconUrl() == null) { - String authorName = mPost.getAuthor().equals("[deleted]") ? mPost.getSubredditNamePrefixed().substring(2) : mPost.getAuthor(); - new LoadUserDataAsyncTask(mRedditDataRoomDatabase.userDao(), authorName, mOauthRetrofit, iconImageUrl -> { - if(mActivity != null && getItemCount() > 0) { - if(iconImageUrl == null || iconImageUrl.equals("")) { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(((PostDetailViewHolder) holder).mIconGifImageView); - } else { - mGlide.load(iconImageUrl) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(((PostDetailViewHolder) holder).mIconGifImageView); - } - - if(holder.getAdapterPosition() >= 0) { - mPost.setAuthorIconUrl(iconImageUrl); - } - } - }).execute(); - } else if(!mPost.getAuthorIconUrl().equals("")) { - mGlide.load(mPost.getAuthorIconUrl()) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(((PostDetailViewHolder) holder).mIconGifImageView); - } else { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(((PostDetailViewHolder) holder).mIconGifImageView); - } - } else { - if(mPost.getSubredditIconUrl() == null) { - new LoadSubredditIconAsyncTask( - mRedditDataRoomDatabase, mPost.getSubredditNamePrefixed().substring(2), - mRetrofit, iconImageUrl -> { - if(iconImageUrl == null || iconImageUrl.equals("")) { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(((PostDetailViewHolder) holder).mIconGifImageView); - } else { - mGlide.load(iconImageUrl) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(((PostDetailViewHolder) holder).mIconGifImageView); - } - - mPost.setSubredditIconUrl(iconImageUrl); - }).execute(); - } else if(!mPost.getSubredditIconUrl().equals("")) { - mGlide.load(mPost.getSubredditIconUrl()) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(((PostDetailViewHolder) holder).mIconGifImageView); - } else { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(((PostDetailViewHolder) holder).mIconGifImageView); - } - } - - switch (mPost.getVoteType()) { - case 1: - //Upvote - ((PostDetailViewHolder) holder).mUpvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.upvoted), PorterDuff.Mode.SRC_IN); - ((PostDetailViewHolder) holder).mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.upvoted)); - break; - case -1: - //Downvote - ((PostDetailViewHolder) holder).mDownvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.downvoted), PorterDuff.Mode.SRC_IN); - ((PostDetailViewHolder) holder).mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.downvoted)); - break; - case 0: - ((PostDetailViewHolder) holder).mUpvoteButton.clearColorFilter(); - ((PostDetailViewHolder) holder).mDownvoteButton.clearColorFilter(); - ((PostDetailViewHolder) holder).mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); - } - - if(mPost.getPostType() != Post.TEXT_TYPE && mPost.getPostType() != Post.NO_PREVIEW_LINK_TYPE) { - ((PostDetailViewHolder) holder).mRelativeLayout.setVisibility(View.VISIBLE); - ((PostDetailViewHolder) holder).mImageView.setVisibility(View.VISIBLE); - ((PostDetailViewHolder) holder).mImageView.setRatio((float) mPost.getPreviewHeight() / (float) mPost.getPreviewWidth()); - loadImage((PostDetailViewHolder) holder); - } else { - ((PostDetailViewHolder) holder).mRelativeLayout.setVisibility(View.GONE); - ((PostDetailViewHolder) holder).mImageView.setVisibility(View.GONE); - } - - if(mPost.isArchived()) { - ((PostDetailViewHolder) holder).mUpvoteButton - .setColorFilter(ContextCompat.getColor(mActivity, R.color.voteAndReplyUnavailableVoteButtonColor), android.graphics.PorterDuff.Mode.SRC_IN); - ((PostDetailViewHolder) holder).mDownvoteButton - .setColorFilter(ContextCompat.getColor(mActivity, R.color.voteAndReplyUnavailableVoteButtonColor), android.graphics.PorterDuff.Mode.SRC_IN); - } - - if(mPost.isCrosspost()) { - ((PostDetailViewHolder) holder).mCrosspostImageView.setOnClickListener(view -> { - Intent crosspostIntent = new Intent(mActivity, ViewPostDetailActivity.class); - crosspostIntent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, mPost.getCrosspostParentId()); - mActivity.startActivity(crosspostIntent); - }); - ((PostDetailViewHolder) holder).mCrosspostImageView.setVisibility(View.VISIBLE); - } - - ((PostDetailViewHolder) holder).mSubredditTextView.setText(mPost.getSubredditNamePrefixed()); - ((PostDetailViewHolder) holder).mUserTextView.setText(mPost.getAuthorNamePrefixed()); - - ((PostDetailViewHolder) holder).mPostTimeTextView.setText(mPost.getPostTime()); - - if(mPost.getGilded() > 0) { - ((PostDetailViewHolder) holder).mGildedImageView.setVisibility(View.VISIBLE); - ((PostDetailViewHolder) holder).mGildedNumberTextView.setVisibility(View.VISIBLE); - String gildedNumber = mActivity.getResources().getString(R.string.gilded_count, mPost.getGilded()); - ((PostDetailViewHolder) holder).mGildedNumberTextView.setText(gildedNumber); - } - - if(mPost.isArchived()) { - ((PostDetailViewHolder) holder).mArchivedImageView.setVisibility(View.VISIBLE); - } - - if(mPost.isLocked()) { - ((PostDetailViewHolder) holder).mLockedImageView.setVisibility(View.VISIBLE); - } - - if(mPost.isSpoiler() || mPost.getFlair() != null) { - ((PostDetailViewHolder) holder).spoilerFlairlinearLayout.setVisibility(View.VISIBLE); - } - - if(mPost.isSpoiler()) { - ((PostDetailViewHolder) holder).spoilerTextView.setVisibility(View.VISIBLE); - } - - if(mPost.getFlair() != null) { - ((PostDetailViewHolder) holder).flairTextView.setVisibility(View.VISIBLE); - ((PostDetailViewHolder) holder).flairTextView.setText(mPost.getFlair()); - } - - if(mPost.isNSFW()) { - ((PostDetailViewHolder) holder).mNSFWTextView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, FilteredThingActivity.class); - intent.putExtra(FilteredThingActivity.EXTRA_NAME, mSubredditNamePrefixed.substring(2)); - intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); - intent.putExtra(FilteredThingActivity.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_HOT); - intent.putExtra(FilteredThingActivity.EXTRA_FILTER, Post.NSFW_TYPE); - mActivity.startActivity(intent); - }); - ((PostDetailViewHolder) holder).mNSFWTextView.setVisibility(View.VISIBLE); - } else { - ((PostDetailViewHolder) holder).mNSFWTextView.setVisibility(View.GONE); - } - - String scoreWithVote = Integer.toString(mPost.getScore() + mPost.getVoteType()); - ((PostDetailViewHolder) holder).mScoreTextView.setText(scoreWithVote); - - ((PostDetailViewHolder) holder).mTypeTextView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, FilteredThingActivity.class); - intent.putExtra(FilteredThingActivity.EXTRA_NAME, mSubredditNamePrefixed.substring(2)); - intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); - intent.putExtra(FilteredThingActivity.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_HOT); - intent.putExtra(FilteredThingActivity.EXTRA_FILTER, mPost.getPostType()); - mActivity.startActivity(intent); - - }); - - switch (mPost.getPostType()) { - case Post.IMAGE_TYPE: - ((PostDetailViewHolder) holder).mTypeTextView.setText("IMAGE"); - - ((PostDetailViewHolder) holder).mImageView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, ViewImageActivity.class); - intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, mPost.getUrl()); - intent.putExtra(ViewImageActivity.TITLE_KEY, mPost.getTitle()); - intent.putExtra(ViewImageActivity.FILE_NAME_KEY, mPost.getSubredditNamePrefixed().substring(2) - + "-" + mPost.getId().substring(3)); - mActivity.startActivity(intent); - }); - break; - case Post.LINK_TYPE: - ((PostDetailViewHolder) holder).mTypeTextView.setText("LINK"); - - ((PostDetailViewHolder) holder).linkTextView.setVisibility(View.VISIBLE); - String domain = Uri.parse(mPost.getUrl()).getHost(); - ((PostDetailViewHolder) holder).linkTextView.setText(domain); - - ((PostDetailViewHolder) holder).mImageView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, LinkResolverActivity.class); - Uri uri = Uri.parse(mPost.getUrl()); - if(uri.getScheme() == null && uri.getHost() == null) { - intent.setData(LinkResolverActivity.getRedditUriByPath(mPost.getUrl())); - } else { - intent.setData(uri); - } - mActivity.startActivity(intent); - }); - break; - case Post.GIF_VIDEO_TYPE: - ((PostDetailViewHolder) holder).mTypeTextView.setText("GIF"); - - final Uri gifVideoUri = Uri.parse(mPost.getVideoUrl()); - ((PostDetailViewHolder) holder).mImageView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, ViewVideoActivity.class); - intent.setData(gifVideoUri); - intent.putExtra(ViewVideoActivity.TITLE_KEY, mPost.getTitle()); - intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, mPost.getSubredditName()); - intent.putExtra(ViewVideoActivity.ID_KEY, mPost.getId()); - mActivity.startActivity(intent); - }); - break; - case Post.VIDEO_TYPE: - ((PostDetailViewHolder) holder).mTypeTextView.setText("VIDEO"); - - final Uri videoUri = Uri.parse(mPost.getVideoUrl()); - ((PostDetailViewHolder) holder).mImageView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, ViewVideoActivity.class); - intent.setData(videoUri); - intent.putExtra(ViewVideoActivity.TITLE_KEY, mPost.getTitle()); - intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, mPost.getSubredditName()); - intent.putExtra(ViewVideoActivity.ID_KEY, mPost.getId()); - mActivity.startActivity(intent); - }); - break; - case Post.NO_PREVIEW_LINK_TYPE: - ((PostDetailViewHolder) holder).mTypeTextView.setText("LINK"); - - ((PostDetailViewHolder) holder).linkTextView.setVisibility(View.VISIBLE); - String noPreviewLinkDomain = Uri.parse(mPost.getUrl()).getHost(); - ((PostDetailViewHolder) holder).linkTextView.setText(noPreviewLinkDomain); - - if(mPost.getSelfText() != null && !mPost.getSelfText().equals("")) { - ((PostDetailViewHolder) holder).mContentMarkdownView.setVisibility(View.VISIBLE); - mMarkwon.setMarkdown(((PostDetailViewHolder) holder).mContentMarkdownView, mPost.getSelfText()); - } - - ((PostDetailViewHolder) holder).mNoPreviewLinkImageView.setVisibility(View.VISIBLE); - ((PostDetailViewHolder) holder).mNoPreviewLinkImageView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, LinkResolverActivity.class); - Uri uri = Uri.parse(mPost.getUrl()); - if(uri.getScheme() == null && uri.getHost() == null) { - intent.setData(LinkResolverActivity.getRedditUriByPath(mPost.getUrl())); - } else { - intent.setData(uri); - } - mActivity.startActivity(intent); - }); - break; - case Post.TEXT_TYPE: - ((PostDetailViewHolder) holder).mTypeTextView.setText("TEXT"); - - if(!mPost.getSelfText().equals("")) { - ((PostDetailViewHolder) holder).mContentMarkdownView.setVisibility(View.VISIBLE); - mMarkwon.setMarkdown(((PostDetailViewHolder) holder).mContentMarkdownView, mPost.getSelfText()); - } - break; - } - - ((PostDetailViewHolder) holder).commentButton.setOnClickListener(view -> { - if(mAccessToken == null) { - Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - Intent intent = new Intent(mActivity, CommentActivity.class); - intent.putExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY, mPost.getFullName()); - intent.putExtra(CommentActivity.EXTRA_COMMENT_PARENT_TEXT_KEY, mPost.getTitle()); - intent.putExtra(CommentActivity.EXTRA_IS_REPLYING_KEY, false); - intent.putExtra(CommentActivity.EXTRA_PARENT_DEPTH_KEY, 0); - mActivity.startActivityForResult(intent, WRITE_COMMENT_REQUEST_CODE); - }); - - ((PostDetailViewHolder) holder).commentsCountTextView.setText(Integer.toString(mPost.getnComments())); - - if(mPost.isSaved()) { - ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); - } else { - ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); - } - - ((PostDetailViewHolder) holder).saveButton.setOnClickListener(view -> { - if(mAccessToken == null) { - Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - if(mPost.isSaved()) { - ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); - SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, mPost.getFullName(), - new SaveThing.SaveThingListener() { - @Override - public void success() { - mPost.setSaved(false); - ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); - Toast.makeText(mActivity, R.string.post_unsaved_success, Toast.LENGTH_SHORT).show(); - mCommentRecyclerViewAdapterCallback.updatePost(mPost); - } - - @Override - public void failed() { - mPost.setSaved(true); - ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); - Toast.makeText(mActivity, R.string.post_unsaved_failed, Toast.LENGTH_SHORT).show(); - mCommentRecyclerViewAdapterCallback.updatePost(mPost); - } - }); - } else { - ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); - SaveThing.saveThing(mOauthRetrofit, mAccessToken, mPost.getFullName(), - new SaveThing.SaveThingListener() { - @Override - public void success() { - mPost.setSaved(true); - ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); - Toast.makeText(mActivity, R.string.post_saved_success, Toast.LENGTH_SHORT).show(); - mCommentRecyclerViewAdapterCallback.updatePost(mPost); - } - - @Override - public void failed() { - mPost.setSaved(false); - ((PostDetailViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); - Toast.makeText(mActivity, R.string.post_saved_failed, Toast.LENGTH_SHORT).show(); - mCommentRecyclerViewAdapterCallback.updatePost(mPost); - } - }); - } - }); - } else if(holder.getItemViewType() == VIEW_TYPE_COMMENT) { - CommentData comment; - if(mIsSingleCommentThreadMode) { - comment = mVisibleComments.get(holder.getAdapterPosition() - 2); - } else { - comment = mVisibleComments.get(holder.getAdapterPosition() - 1); - } - - if(mIsSingleCommentThreadMode && comment.getId().equals(mSingleCommentId)) { - ((CommentViewHolder) holder).itemView.setBackgroundColor( - mActivity.getResources().getColor(R.color.singleCommentThreadBackgroundColor)); - } - - String authorPrefixed = "u/" + comment.getAuthor(); - ((CommentViewHolder) holder).authorTextView.setText(authorPrefixed); - - if(comment.isSubmitter()) { - ((CommentViewHolder) holder).authorTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.submitter)); - ((CommentViewHolder) holder).authorTypeImageView.setVisibility(View.VISIBLE); - ((CommentViewHolder) holder).authorTypeImageView. - setColorFilter(ContextCompat.getColor(mActivity, R.color.submitter), android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).authorTypeImageView.setImageResource(R.drawable.ic_mic_14dp); - } else if(comment.isModerator()) { - ((CommentViewHolder) holder).authorTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.moderator)); - ((CommentViewHolder) holder).authorTypeImageView.setVisibility(View.VISIBLE); - ((CommentViewHolder) holder).authorTypeImageView. - setColorFilter(ContextCompat.getColor(mActivity, R.color.moderator), android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).authorTypeImageView.setImageResource(R.drawable.ic_verified_user_14dp); - } - - ((CommentViewHolder) holder).commentTimeTextView.setText(comment.getCommentTime()); - - mMarkwon.setMarkdown(((CommentViewHolder) holder).commentMarkdownView, comment.getCommentContent()); - ((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType())); - - ((CommentViewHolder) holder).itemView.setPadding(comment.getDepth() * 16, 0, 0, 0); - if(comment.getDepth() > 0) { - switch (comment.getDepth() % 7) { - case 0: - ((CommentViewHolder) holder).verticalBlock - .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar7)); - break; - case 1: - ((CommentViewHolder) holder).verticalBlock - .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar1)); - break; - case 2: - ((CommentViewHolder) holder).verticalBlock - .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar2)); - break; - case 3: - ((CommentViewHolder) holder).verticalBlock - .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar3)); - break; - case 4: - ((CommentViewHolder) holder).verticalBlock - .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar4)); - break; - case 5: - ((CommentViewHolder) holder).verticalBlock - .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar5)); - break; - case 6: - ((CommentViewHolder) holder).verticalBlock - .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar6)); - break; - } - ViewGroup.LayoutParams params = ((CommentViewHolder) holder).verticalBlock.getLayoutParams(); - params.width = 16; - ((CommentViewHolder) holder).verticalBlock.setLayoutParams(params); - } - - if(!mPost.isArchived() && !mPost.isLocked() && comment.getAuthor().equals(mAccountName)) { - ((CommentViewHolder) holder).moreButton.setVisibility(View.VISIBLE); - - ((CommentViewHolder) holder).moreButton.setOnClickListener(view -> { - ModifyCommentBottomSheetFragment modifyCommentBottomSheetFragment = new ModifyCommentBottomSheetFragment(); - Bundle bundle = new Bundle(); - bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_COMMENT_CONTENT, comment.getCommentContent()); - bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_COMMENT_FULLNAME, comment.getFullName()); - if(mIsSingleCommentThreadMode) { - bundle.putInt(ModifyCommentBottomSheetFragment.EXTRA_POSITION, holder.getAdapterPosition() - 2); - } else { - bundle.putInt(ModifyCommentBottomSheetFragment.EXTRA_POSITION, holder.getAdapterPosition() - 1); - } - modifyCommentBottomSheetFragment.setArguments(bundle); - modifyCommentBottomSheetFragment.show(((AppCompatActivity) mActivity).getSupportFragmentManager(), modifyCommentBottomSheetFragment.getTag()); - }); - } - - if (comment.hasReply()) { - if(comment.isExpanded()) { - ((CommentViewHolder) holder).expandButton.setImageResource(R.drawable.ic_expand_less_black_20dp); - } else { - ((CommentViewHolder) holder).expandButton.setImageResource(R.drawable.ic_expand_more_black_20dp); - } - ((CommentViewHolder) holder).expandButton.setVisibility(View.VISIBLE); - } - - switch (comment.getVoteType()) { - case CommentData.VOTE_TYPE_UPVOTE: - ((CommentViewHolder) holder).upVoteButton - .setColorFilter(ContextCompat.getColor(mActivity, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.upvoted)); - break; - case CommentData.VOTE_TYPE_DOWNVOTE: - ((CommentViewHolder) holder).downVoteButton - .setColorFilter(ContextCompat.getColor(mActivity, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.downvoted)); - break; - } - - if(mPost.isArchived()) { - ((CommentViewHolder) holder).replyButton - .setColorFilter(ContextCompat.getColor(mActivity, R.color.voteAndReplyUnavailableVoteButtonColor), - android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).upVoteButton - .setColorFilter(ContextCompat.getColor(mActivity, R.color.voteAndReplyUnavailableVoteButtonColor), - android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).downVoteButton - .setColorFilter(ContextCompat.getColor(mActivity, R.color.voteAndReplyUnavailableVoteButtonColor), - android.graphics.PorterDuff.Mode.SRC_IN); - } - - if(mPost.isLocked()) { - ((CommentViewHolder) holder).replyButton - .setColorFilter(ContextCompat.getColor(mActivity, R.color.voteAndReplyUnavailableVoteButtonColor), - android.graphics.PorterDuff.Mode.SRC_IN); - } - - ((CommentViewHolder) holder).replyButton.setOnClickListener(view -> { - if(mAccessToken == null) { - Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - if(mPost.isArchived()) { - Toast.makeText(mActivity, R.string.archived_post_reply_unavailable, Toast.LENGTH_SHORT).show(); - return; - } - - if(mPost.isLocked()) { - Toast.makeText(mActivity, R.string.locked_post_reply_unavailable, Toast.LENGTH_SHORT).show(); - return; - } - - Intent intent = new Intent(mActivity, CommentActivity.class); - intent.putExtra(CommentActivity.EXTRA_PARENT_DEPTH_KEY, comment.getDepth() + 1); - intent.putExtra(CommentActivity.EXTRA_COMMENT_PARENT_TEXT_KEY, comment.getCommentContent()); - intent.putExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY, comment.getFullName()); - intent.putExtra(CommentActivity.EXTRA_IS_REPLYING_KEY, true); - - int parentPosition = mIsSingleCommentThreadMode ? holder.getAdapterPosition() - 2 : holder.getAdapterPosition() - 1; - intent.putExtra(CommentActivity.EXTRA_PARENT_POSITION_KEY, parentPosition); - mActivity.startActivityForResult(intent, CommentActivity.WRITE_COMMENT_REQUEST_CODE); - }); - - ((CommentViewHolder) holder).upVoteButton.setOnClickListener(view -> { - if(mPost.isArchived()) { - Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); - return; - } - - if(mAccessToken == null) { - Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - int commentPosition = mIsSingleCommentThreadMode ? holder.getAdapterPosition() - 2 : holder.getAdapterPosition() - 1; - - int previousVoteType = mVisibleComments.get(commentPosition).getVoteType(); - String newVoteType; - - ((CommentViewHolder) holder).downVoteButton.clearColorFilter(); - - if(previousVoteType != CommentData.VOTE_TYPE_UPVOTE) { - //Not upvoted before - mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_UPVOTE); - newVoteType = RedditUtils.DIR_UPVOTE; - ((CommentViewHolder) holder).upVoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.upvoted)); - } else { - //Upvoted before - mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_NO_VOTE); - newVoteType = RedditUtils.DIR_UNVOTE; - ((CommentViewHolder) holder).upVoteButton.clearColorFilter(); - ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); - } - - ((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(mVisibleComments.get(commentPosition).getScore() + mVisibleComments.get(commentPosition).getVoteType())); - - VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { - @Override - public void onVoteThingSuccess(int position) { - if(newVoteType.equals(RedditUtils.DIR_UPVOTE)) { - mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_UPVOTE); - ((CommentViewHolder) holder).upVoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.upvoted)); - } else { - mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_NO_VOTE); - ((CommentViewHolder) holder).upVoteButton.clearColorFilter(); - ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); - } - - ((CommentViewHolder) holder).downVoteButton.clearColorFilter(); - ((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(mVisibleComments.get(commentPosition).getScore() + mVisibleComments.get(commentPosition).getVoteType())); - } - - @Override - public void onVoteThingFail(int position) { } - }, mVisibleComments.get(commentPosition).getFullName(), newVoteType, holder.getAdapterPosition()); - }); - - ((CommentViewHolder) holder).downVoteButton.setOnClickListener(view -> { - if(mPost.isArchived()) { - Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); - return; - } - - if(mAccessToken == null) { - Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - int commentPosition = mIsSingleCommentThreadMode ? holder.getAdapterPosition() - 2 : holder.getAdapterPosition() - 1; - - int previousVoteType = mVisibleComments.get(commentPosition).getVoteType(); - String newVoteType; - - ((CommentViewHolder) holder).upVoteButton.clearColorFilter(); - - if(previousVoteType != CommentData.VOTE_TYPE_DOWNVOTE) { - //Not downvoted before - mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_DOWNVOTE); - newVoteType = RedditUtils.DIR_DOWNVOTE; - ((CommentViewHolder) holder).downVoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.downvoted)); - } else { - //Downvoted before - mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_NO_VOTE); - newVoteType = RedditUtils.DIR_UNVOTE; - ((CommentViewHolder) holder).downVoteButton.clearColorFilter(); - ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); - } - - ((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(mVisibleComments.get(commentPosition).getScore() + mVisibleComments.get(commentPosition).getVoteType())); - - VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { - @Override - public void onVoteThingSuccess(int position1) { - if(newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) { - mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_DOWNVOTE); - ((CommentViewHolder) holder).downVoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.downvoted)); - } else { - mVisibleComments.get(commentPosition).setVoteType(CommentData.VOTE_TYPE_NO_VOTE); - ((CommentViewHolder) holder).downVoteButton.clearColorFilter(); - ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); - } - - ((CommentViewHolder) holder).upVoteButton.clearColorFilter(); - ((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(mVisibleComments.get(commentPosition).getScore() + mVisibleComments.get(commentPosition).getVoteType())); - } - - @Override - public void onVoteThingFail(int position1) { } - }, mVisibleComments.get(commentPosition).getFullName(), newVoteType, holder.getAdapterPosition()); - }); - - if(comment.isSaved()) { - ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_20dp); - } else { - ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_20dp); - } - - ((CommentViewHolder) holder).saveButton.setOnClickListener(view -> { - if (comment.isSaved()) { - comment.setSaved(false); - SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, comment.getFullName(), new SaveThing.SaveThingListener() { - @Override - public void success() { - comment.setSaved(false); - ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_20dp); - Toast.makeText(mActivity, R.string.comment_unsaved_success, Toast.LENGTH_SHORT).show(); - } - - @Override - public void failed() { - comment.setSaved(true); - ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_20dp); - Toast.makeText(mActivity, R.string.comment_unsaved_failed, Toast.LENGTH_SHORT).show(); - } - }); - } else { - comment.setSaved(true); - SaveThing.saveThing(mOauthRetrofit, mAccessToken, comment.getFullName(), new SaveThing.SaveThingListener() { - @Override - public void success() { - comment.setSaved(true); - ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_20dp); - Toast.makeText(mActivity, R.string.comment_saved_success, Toast.LENGTH_SHORT).show(); - } - - @Override - public void failed() { - comment.setSaved(false); - ((CommentViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_20dp); - Toast.makeText(mActivity, R.string.comment_saved_failed, Toast.LENGTH_SHORT).show(); - } - }); - } - }); - } else if(holder instanceof LoadMoreChildCommentsViewHolder) { - CommentData placeholder; - placeholder = mIsSingleCommentThreadMode ? mVisibleComments.get(holder.getAdapterPosition() - 2) - : mVisibleComments.get(holder.getAdapterPosition() - 1); - - ((LoadMoreChildCommentsViewHolder) holder).itemView.setPadding(placeholder.getDepth() * 16, 0, 0, 0); - if(placeholder.getDepth() > 0) { - switch (placeholder.getDepth() % 7) { - case 0: - ((LoadMoreChildCommentsViewHolder) holder).verticalBlock - .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar7)); - break; - case 1: - ((LoadMoreChildCommentsViewHolder) holder).verticalBlock - .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar1)); - break; - case 2: - ((LoadMoreChildCommentsViewHolder) holder).verticalBlock - .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar2)); - break; - case 3: - ((LoadMoreChildCommentsViewHolder) holder).verticalBlock - .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar3)); - break; - case 4: - ((LoadMoreChildCommentsViewHolder) holder).verticalBlock - .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar4)); - break; - case 5: - ((LoadMoreChildCommentsViewHolder) holder).verticalBlock - .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar5)); - break; - case 6: - ((LoadMoreChildCommentsViewHolder) holder).verticalBlock - .setBackgroundColor(ContextCompat.getColor(mActivity, R.color.commentVerticalBar6)); - break; - } - - ViewGroup.LayoutParams params = ((LoadMoreChildCommentsViewHolder) holder).verticalBlock.getLayoutParams(); - params.width = 16; - ((LoadMoreChildCommentsViewHolder) holder).verticalBlock.setLayoutParams(params); - } - - if(placeholder.isLoadingMoreChildren()) { - ((LoadMoreChildCommentsViewHolder) holder).placeholderTextView.setText(R.string.loading); - } else if(placeholder.isLoadMoreChildrenFailed()) { - ((LoadMoreChildCommentsViewHolder) holder).placeholderTextView.setText(R.string.comment_load_more_comments_failed); - } else { - ((LoadMoreChildCommentsViewHolder) holder).placeholderTextView.setText(R.string.comment_load_more_comments); - } - } else if(holder instanceof LoadMoreCommentsFailedViewHolder) { - ((LoadMoreCommentsFailedViewHolder) holder).errorTextView.setText(R.string.load_comments_failed); - } - } - - private void loadImage(PostDetailViewHolder holder) { - RequestBuilder imageRequestBuilder = mGlide.load(mPost.getPreviewUrl()) - .listener(new RequestListener() { - @Override - public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { - holder.mLoadImageProgressBar.setVisibility(View.GONE); - holder.mLoadImageErrorTextView.setVisibility(View.VISIBLE); - holder.mLoadImageErrorTextView.setOnClickListener(view -> { - holder.mLoadImageProgressBar.setVisibility(View.VISIBLE); - holder.mLoadImageErrorTextView.setVisibility(View.GONE); - loadImage(holder); - }); - return false; - } - - @Override - public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { - holder.mLoadWrapper.setVisibility(View.GONE); - return false; - } - }); - - if((mPost.isNSFW() && mNeedBlurNSFW) || (mPost.isSpoiler() && mNeedBlurSpoiler)) { - imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 2))) - .into(holder.mImageView); - } else { - imageRequestBuilder.into(holder.mImageView); - } - } - - void updatePost(Post post) { - mPost = post; - notifyItemChanged(0); - } - - private int getParentPosition(int position) { - if(position >= mVisibleComments.size()) { - return -1; - } - - int childDepth = mVisibleComments.get(position).getDepth(); - for(int i = position; i >= 0; i--) { - if(mVisibleComments.get(i).getDepth() < childDepth) { - return i; - } - } - return -1; - } - - private void expandChildren(int position) { - CommentData comment = mVisibleComments.get(position); - if(!comment.isExpanded()) { - comment.setExpanded(true); - ArrayList children = comment.getChildren(); - if(children != null && children.size() > 0) { - for(int i = 0; i < children.size(); i++) { - children.get(i).setExpanded(false); - } - mVisibleComments.addAll(position + 1, children); - if(mIsSingleCommentThreadMode) { - notifyItemRangeInserted(position + 3, children.size()); - } else { - notifyItemRangeInserted(position + 2, children.size()); - } - } - } - } - - private void collapseChildren(int position) { - mVisibleComments.get(position).setExpanded(false); - int depth = mVisibleComments.get(position).getDepth(); - int allChildrenSize = 0; - for(int i = position + 1; i < mVisibleComments.size(); i++) { - if(mVisibleComments.get(i).getDepth() > depth) { - allChildrenSize++; - } else { - break; - } - } - - mVisibleComments.subList(position + 1, position + 1 + allChildrenSize).clear(); - if(mIsSingleCommentThreadMode) { - notifyItemRangeRemoved(position + 3, allChildrenSize); - } else { - notifyItemRangeRemoved(position + 2, allChildrenSize); - } - } - - void addComments(ArrayList comments, boolean hasMoreComments) { - if(mVisibleComments.size() == 0) { - isInitiallyLoading = false; - isInitiallyLoadingFailed = false; - if(comments.size() == 0) { - notifyItemChanged(1); - } else { - notifyItemRemoved(1); - } - } - - int sizeBefore = mVisibleComments.size(); - mVisibleComments.addAll(comments); - if(mIsSingleCommentThreadMode) { - notifyItemRangeInserted(sizeBefore + 2, comments.size()); - } else { - notifyItemRangeInserted(sizeBefore + 1, comments.size()); - } - - if(mHasMoreComments != hasMoreComments) { - if(hasMoreComments) { - if(mIsSingleCommentThreadMode) { - notifyItemInserted(mVisibleComments.size() + 2); - } else { - notifyItemInserted(mVisibleComments.size() + 1); - } - } else { - if(mIsSingleCommentThreadMode) { - notifyItemRemoved(mVisibleComments.size() + 2); - } else { - notifyItemRemoved(mVisibleComments.size() + 1); - } - } - } - mHasMoreComments = hasMoreComments; - } - - void addComment(CommentData comment) { - if(mVisibleComments.size() == 0 || isInitiallyLoadingFailed) { - notifyItemRemoved(1); - } - - mVisibleComments.add(0, comment); - - if(isInitiallyLoading) { - notifyItemInserted(2); - } else { - notifyItemInserted(1); - } - } - - void addChildComment(CommentData comment, String parentFullname, int parentPosition) { - if(!parentFullname.equals(mVisibleComments.get(parentPosition).getFullName())) { - for(int i = 0; i < mVisibleComments.size(); i++) { - if(parentFullname.equals(mVisibleComments.get(i).getFullName())) { - parentPosition = i; - break; - } - } - } - - mVisibleComments.get(parentPosition).addChild(comment); - mVisibleComments.get(parentPosition).setHasReply(true); - if(!mVisibleComments.get(parentPosition).isExpanded()) { - expandChildren(parentPosition); - if(mIsSingleCommentThreadMode) { - notifyItemChanged(parentPosition + 2); - } else { - notifyItemChanged(parentPosition + 1); - } - } else { - mVisibleComments.add(parentPosition + 1, comment); - if(mIsSingleCommentThreadMode) { - notifyItemInserted(parentPosition + 3); - } else { - notifyItemInserted(parentPosition + 2); - } - } - } - - void setSingleComment(String singleCommentId, boolean isSingleCommentThreadMode) { - mSingleCommentId = singleCommentId; - mIsSingleCommentThreadMode = isSingleCommentThreadMode; - } - - ArrayList getVisibleComments() { - return mVisibleComments; - } - - void initiallyLoading() { - if(mVisibleComments.size() != 0) { - int previousSize = mVisibleComments.size(); - mVisibleComments.clear(); - if(mIsSingleCommentThreadMode) { - notifyItemRangeRemoved(1, previousSize + 1); - } else { - notifyItemRangeRemoved(1, previousSize); - } - } - - if(isInitiallyLoading || isInitiallyLoadingFailed || mVisibleComments.size() == 0) { - isInitiallyLoading = true; - isInitiallyLoadingFailed = false; - notifyItemChanged(1); - } else { - isInitiallyLoading = true; - isInitiallyLoadingFailed = false; - notifyItemInserted(1); - } - } - - void initiallyLoadCommentsFailed() { - isInitiallyLoading = false; - isInitiallyLoadingFailed = true; - notifyItemChanged(1); - } - - void loadMoreCommentsFailed() { - loadMoreCommentsFailed = true; - if(mIsSingleCommentThreadMode) { - notifyItemChanged(mVisibleComments.size() + 2); - } else { - notifyItemChanged(mVisibleComments.size() + 1); - } - } - - void editComment(String commentContent, int position) { - mVisibleComments.get(position).setCommentContent(commentContent); - if(mIsSingleCommentThreadMode) { - notifyItemChanged(position + 2); - } else { - notifyItemChanged(position + 1); - } - } - - void deleteComment(int position) { - if(mVisibleComments.get(position).hasReply()) { - mVisibleComments.get(position).setAuthor("[deleted]"); - mVisibleComments.get(position).setCommentContent("[deleted]"); - if(mIsSingleCommentThreadMode) { - notifyItemChanged(position + 2); - } else { - notifyItemChanged(position + 1); - } - } else { - mVisibleComments.remove(position); - if(mIsSingleCommentThreadMode) { - notifyItemRemoved(position + 2); - } else { - notifyItemRemoved(position + 1); - } - } - } - - void setBlurNSFW(boolean needBlurNSFW) { - mNeedBlurNSFW = needBlurNSFW; - } - - void setBlurSpoiler(boolean needBlurSpoiler) { - mNeedBlurSpoiler = needBlurSpoiler; - } - - @Override - public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { - if (holder instanceof CommentViewHolder) { - ((CommentViewHolder) holder).authorTextView.setTextColor( - ContextCompat.getColor(mActivity, R.color.colorPrimaryDarkDayNightTheme)); - mGlide.clear(((CommentViewHolder) holder).authorTypeImageView); - ((CommentViewHolder) holder).authorTypeImageView.setVisibility(View.GONE); - ((CommentViewHolder) holder).moreButton.setVisibility(View.GONE); - ((CommentViewHolder) holder).expandButton.setVisibility(View.GONE); - ((CommentViewHolder) holder).upVoteButton.clearColorFilter(); - ((CommentViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); - ((CommentViewHolder) holder).downVoteButton.clearColorFilter(); - ((CommentViewHolder) holder).replyButton.clearColorFilter(); - ViewGroup.LayoutParams params = ((CommentViewHolder) holder).verticalBlock.getLayoutParams(); - params.width = 0; - ((CommentViewHolder) holder).verticalBlock.setLayoutParams(params); - ((CommentViewHolder) holder).itemView.setPadding(0, 0, 0, 0); - ((CommentViewHolder) holder).itemView.setBackgroundColor( - mActivity.getResources().getColor(R.color.cardViewBackgroundColor)); - } else if(holder instanceof PostDetailViewHolder) { - ((PostDetailViewHolder) holder).mUpvoteButton.clearColorFilter(); - ((PostDetailViewHolder) holder).mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); - ((PostDetailViewHolder) holder).mDownvoteButton.clearColorFilter(); - ((PostDetailViewHolder) holder).spoilerFlairlinearLayout.setVisibility(View.GONE); - ((PostDetailViewHolder) holder).flairTextView.setVisibility(View.GONE); - ((PostDetailViewHolder) holder).spoilerTextView.setVisibility(View.GONE); - ((PostDetailViewHolder) holder).mNSFWTextView.setVisibility(View.GONE); - } else if(holder instanceof LoadMoreChildCommentsViewHolder) { - ((LoadMoreChildCommentsViewHolder) holder).itemView.setPadding(0, 0, 0, 0); - ViewGroup.LayoutParams params = ((LoadMoreChildCommentsViewHolder) holder).verticalBlock.getLayoutParams(); - params.width = 0; - ((LoadMoreChildCommentsViewHolder) holder).verticalBlock.setLayoutParams(params); - } - } - - @Override - public int getItemCount() { - if(isInitiallyLoading || isInitiallyLoadingFailed || mVisibleComments.size() == 0) { - return 2; - } - - if(mHasMoreComments || loadMoreCommentsFailed) { - if(mIsSingleCommentThreadMode) { - return mVisibleComments.size() + 3; - } else { - return mVisibleComments.size() + 2; - } - } - - if(mIsSingleCommentThreadMode) { - return mVisibleComments.size() + 2; - } else { - return mVisibleComments.size() + 1; - } - } - - class PostDetailViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.icon_gif_image_view_item_post_detail) AspectRatioGifImageView mIconGifImageView; - @BindView(R.id.subreddit_text_view_item_post_detail) TextView mSubredditTextView; - @BindView(R.id.user_text_view_item_post_detail) TextView mUserTextView; - @BindView(R.id.post_time_text_view_item_post_detail) TextView mPostTimeTextView; - @BindView(R.id.title_text_view_item_post_detail) TextView mTitleTextView; - @BindView(R.id.content_markdown_view_item_post_detail) TextView mContentMarkdownView; - @BindView(R.id.type_text_view_item_post_detail) CustomTextView mTypeTextView; - @BindView(R.id.gilded_image_view_item_post_detail) ImageView mGildedImageView; - @BindView(R.id.gilded_number_text_view_item_post_detail) TextView mGildedNumberTextView; - @BindView(R.id.crosspost_image_view_item_post_detail) ImageView mCrosspostImageView; - @BindView(R.id.archived_image_view_item_post_detail) ImageView mArchivedImageView; - @BindView(R.id.locked_image_view_item_post_detail) ImageView mLockedImageView; - @BindView(R.id.nsfw_text_view_item_post_detail) CustomTextView mNSFWTextView; - @BindView(R.id.spoiler_flair_linear_layout_item_post_detail) LinearLayout spoilerFlairlinearLayout; - @BindView(R.id.spoiler_custom_text_view_item_post_detail) CustomTextView spoilerTextView; - @BindView(R.id.flair_custom_text_view_item_post_detail) CustomTextView flairTextView; - @BindView(R.id.link_text_view_item_post_detail) TextView linkTextView; - @BindView(R.id.image_view_wrapper_item_post_detail) RelativeLayout mRelativeLayout; - @BindView(R.id.load_wrapper_item_post_detail) RelativeLayout mLoadWrapper; - @BindView(R.id.progress_bar_item_post_detail) ProgressBar mLoadImageProgressBar; - @BindView(R.id.load_image_error_text_view_item_post_detail) TextView mLoadImageErrorTextView; - @BindView(R.id.image_view_item_post_detail) AspectRatioImageView mImageView; - @BindView(R.id.image_view_no_preview_link_item_post_detail) ImageView mNoPreviewLinkImageView; - @BindView(R.id.plus_button_item_post_detail) ImageView mUpvoteButton; - @BindView(R.id.score_text_view_item_post_detail) TextView mScoreTextView; - @BindView(R.id.minus_button_item_post_detail) ImageView mDownvoteButton; - @BindView(R.id.comment_button_item_post_detail) ImageView commentButton; - @BindView(R.id.comments_count_item_post_detail) TextView commentsCountTextView; - @BindView(R.id.save_button_item_post_detail) ImageView saveButton; - @BindView(R.id.share_button_item_post_detail) ImageView mShareButton; - - PostDetailViewHolder(@NonNull View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - - mIconGifImageView.setOnClickListener(view -> mSubredditTextView.performClick()); - - mSubredditTextView.setOnClickListener(view -> { - Intent intent; - if(mPost.getSubredditNamePrefixed().equals("u/" + mPost.getAuthor())) { - intent = new Intent(mActivity, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mPost.getAuthor()); - } else { - intent = new Intent(mActivity, ViewSubredditDetailActivity.class); - intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, - mPost.getSubredditNamePrefixed().substring(2)); - } - mActivity.startActivity(intent); - }); - - mUserTextView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mPost.getAuthor()); - mActivity.startActivity(intent); - }); - - mShareButton.setOnClickListener(view -> { - try { - Intent intent = new Intent(Intent.ACTION_SEND); - intent.setType("text/plain"); - String extraText = mPost.getTitle() + "\n" + mPost.getPermalink(); - intent.putExtra(Intent.EXTRA_TEXT, extraText); - mActivity.startActivity(Intent.createChooser(intent, mActivity.getString(R.string.share))); - } catch (ActivityNotFoundException e) { - Toast.makeText(mActivity, R.string.no_activity_found_for_share, Toast.LENGTH_SHORT).show(); - } - }); - - mUpvoteButton.setOnClickListener(view -> { - if(mPost.isArchived()) { - Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); - return; - } - - if(mAccessToken == null) { - Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - ColorFilter previousUpvoteButtonColorFilter = mUpvoteButton.getColorFilter(); - ColorFilter previousDownvoteButtonColorFilter = mDownvoteButton.getColorFilter(); - int previousScoreTextViewColor = mScoreTextView.getCurrentTextColor(); - - int previousVoteType = mPost.getVoteType(); - String newVoteType; - - mDownvoteButton.clearColorFilter(); - - if(previousUpvoteButtonColorFilter == null) { - //Not upvoted before - mPost.setVoteType(1); - newVoteType = RedditUtils.DIR_UPVOTE; - mUpvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); - mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.upvoted)); - } else { - //Upvoted before - mPost.setVoteType(0); - newVoteType = RedditUtils.DIR_UNVOTE; - mUpvoteButton.clearColorFilter(); - mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); - } - - mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType())); - - mCommentRecyclerViewAdapterCallback.updatePost(mPost); - - VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingWithoutPositionListener() { - @Override - public void onVoteThingSuccess() { - if(newVoteType.equals(RedditUtils.DIR_UPVOTE)) { - mPost.setVoteType(1); - mUpvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); - mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.upvoted)); - } else { - mPost.setVoteType(0); - mUpvoteButton.clearColorFilter(); - mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); - } - - mDownvoteButton.clearColorFilter(); - mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType())); - - mCommentRecyclerViewAdapterCallback.updatePost(mPost); - } - - @Override - public void onVoteThingFail() { - Toast.makeText(mActivity, R.string.vote_failed, Toast.LENGTH_SHORT).show(); - mPost.setVoteType(previousVoteType); - mScoreTextView.setText(Integer.toString(mPost.getScore() + previousVoteType)); - mUpvoteButton.setColorFilter(previousUpvoteButtonColorFilter); - mDownvoteButton.setColorFilter(previousDownvoteButtonColorFilter); - mScoreTextView.setTextColor(previousScoreTextViewColor); - - mCommentRecyclerViewAdapterCallback.updatePost(mPost); - } - }, mPost.getFullName(), newVoteType); - }); - - mDownvoteButton.setOnClickListener(view -> { - if(mPost.isArchived()) { - Toast.makeText(mActivity, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); - return; - } - - if(mAccessToken == null) { - Toast.makeText(mActivity, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - ColorFilter previousUpvoteButtonColorFilter = mUpvoteButton.getColorFilter(); - ColorFilter previousDownvoteButtonColorFilter = mDownvoteButton.getColorFilter(); - int previousScoreTextViewColor = mScoreTextView.getCurrentTextColor(); - - int previousVoteType = mPost.getVoteType(); - String newVoteType; - - mUpvoteButton.clearColorFilter(); - - if(previousDownvoteButtonColorFilter == null) { - //Not upvoted before - mPost.setVoteType(-1); - newVoteType = RedditUtils.DIR_DOWNVOTE; - mDownvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); - mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.downvoted)); - } else { - //Upvoted before - mPost.setVoteType(0); - newVoteType = RedditUtils.DIR_UNVOTE; - mDownvoteButton.clearColorFilter(); - mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); - } - - mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType())); - - mCommentRecyclerViewAdapterCallback.updatePost(mPost); - - VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingWithoutPositionListener() { - @Override - public void onVoteThingSuccess() { - if(newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) { - mPost.setVoteType(-1); - mDownvoteButton.setColorFilter(ContextCompat.getColor(mActivity, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); - mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.downvoted)); - } else { - mPost.setVoteType(0); - mDownvoteButton.clearColorFilter(); - mScoreTextView.setTextColor(ContextCompat.getColor(mActivity, R.color.defaultTextColor)); - } - - mUpvoteButton.clearColorFilter(); - mScoreTextView.setText(Integer.toString(mPost.getScore() + mPost.getVoteType())); - - mCommentRecyclerViewAdapterCallback.updatePost(mPost); - } - - @Override - public void onVoteThingFail() { - Toast.makeText(mActivity, R.string.vote_failed, Toast.LENGTH_SHORT).show(); - mPost.setVoteType(previousVoteType); - mScoreTextView.setText(Integer.toString(mPost.getScore() + previousVoteType)); - mUpvoteButton.setColorFilter(previousUpvoteButtonColorFilter); - mDownvoteButton.setColorFilter(previousDownvoteButtonColorFilter); - mScoreTextView.setTextColor(previousScoreTextViewColor); - - mCommentRecyclerViewAdapterCallback.updatePost(mPost); - } - }, mPost.getFullName(), newVoteType); - }); - } - } - - class CommentViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.author_text_view_item_post_comment) TextView authorTextView; - @BindView(R.id.author_type_image_view_item_comment) ImageView authorTypeImageView; - @BindView(R.id.comment_time_text_view_item_post_comment) TextView commentTimeTextView; - @BindView(R.id.comment_markdown_view_item_post_comment) TextView commentMarkdownView; - @BindView(R.id.up_vote_button_item_post_comment) ImageView upVoteButton; - @BindView(R.id.score_text_view_item_post_comment) TextView scoreTextView; - @BindView(R.id.down_vote_button_item_post_comment) ImageView downVoteButton; - @BindView(R.id.more_button_item_post_comment) ImageView moreButton; - @BindView(R.id.save_button_item_post_comment) ImageView saveButton; - @BindView(R.id.expand_button_item_post_comment) ImageView expandButton; - @BindView(R.id.share_button_item_post_comment) ImageView shareButton; - @BindView(R.id.reply_button_item_post_comment) ImageView replyButton; - @BindView(R.id.vertical_block_item_post_comment) View verticalBlock; - - CommentViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - - authorTextView.setOnClickListener(view -> { - Intent intent = new Intent(mActivity, ViewUserDetailActivity.class); - if(mIsSingleCommentThreadMode) { - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mVisibleComments.get(getAdapterPosition() - 2).getAuthor()); - } else { - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mVisibleComments.get(getAdapterPosition() - 1).getAuthor()); - } - mActivity.startActivity(intent); - }); - - shareButton.setOnClickListener(view -> { - try { - Intent intent = new Intent(Intent.ACTION_SEND); - intent.setType("text/plain"); - String extraText = mIsSingleCommentThreadMode ? mVisibleComments.get(getAdapterPosition() - 2).getPermalink() - : mVisibleComments.get(getAdapterPosition() - 1).getPermalink(); - intent.putExtra(Intent.EXTRA_TEXT, extraText); - mActivity.startActivity(Intent.createChooser(intent, mActivity.getString(R.string.share))); - } catch (ActivityNotFoundException e) { - Toast.makeText(mActivity, R.string.no_activity_found_for_share, Toast.LENGTH_SHORT).show(); - } - }); - - expandButton.setOnClickListener(view -> { - if(expandButton.getVisibility() == View.VISIBLE) { - int commentPosition = mIsSingleCommentThreadMode ? getAdapterPosition() - 2 : getAdapterPosition() - 1; - if(mVisibleComments.get(commentPosition).isExpanded()) { - collapseChildren(commentPosition); - expandButton.setImageResource(R.drawable.ic_expand_more_black_20dp); - } else { - expandChildren(commentPosition); - mVisibleComments.get(commentPosition).setExpanded(true); - expandButton.setImageResource(R.drawable.ic_expand_less_black_20dp); - } - } - }); - - commentMarkdownView.setOnLongClickListener(view -> { - expandButton.performClick(); - return true; - }); - - itemView.setOnLongClickListener(view -> { - expandButton.performClick(); - return true; - }); - } - } - - class LoadMoreChildCommentsViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.vertical_block_item_load_more_comments) View verticalBlock; - @BindView(R.id.placeholder_text_view_item_load_more_comments) TextView placeholderTextView; - - LoadMoreChildCommentsViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - - placeholderTextView.setOnClickListener(view -> { - int commentPosition = mIsSingleCommentThreadMode ? getAdapterPosition() - 2 : getAdapterPosition() - 1; - int parentPosition = getParentPosition(commentPosition); - CommentData parentComment = mVisibleComments.get(parentPosition); - - mVisibleComments.get(commentPosition).setLoadingMoreChildren(true); - mVisibleComments.get(commentPosition).setLoadMoreChildrenFailed(false); - placeholderTextView.setText(R.string.loading); - - Retrofit retrofit = mAccessToken == null ? mRetrofit : mOauthRetrofit; - FetchComment.fetchMoreComment(retrofit, mAccessToken, parentComment.getMoreChildrenFullnames(), - parentComment.getMoreChildrenStartingIndex(), parentComment.getDepth() + 1, mLocale, - new FetchComment.FetchMoreCommentListener() { - @Override - public void onFetchMoreCommentSuccess(ArrayList expandedComments, - int childrenStartingIndex) { - if(mVisibleComments.size() > parentPosition - && parentComment.getFullName().equals(mVisibleComments.get(parentPosition).getFullName())) { - if(mVisibleComments.get(parentPosition).isExpanded()) { - if(mVisibleComments.get(parentPosition).getChildren().size() > childrenStartingIndex) { - mVisibleComments.get(parentPosition).setMoreChildrenStartingIndex(childrenStartingIndex); - mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1) - .setLoadingMoreChildren(false); - mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1) - .setLoadMoreChildrenFailed(false); - - int placeholderPosition = commentPosition; - if(mVisibleComments.get(commentPosition).getFullName().equals(parentComment.getFullName())) { - for(int i = parentPosition + 1; i < mVisibleComments.size(); i++) { - if(mVisibleComments.get(i).getFullName().equals(parentComment.getFullName())) { - placeholderPosition = i; - break; - } - } - } - - mVisibleComments.get(placeholderPosition).setLoadingMoreChildren(false); - mVisibleComments.get(placeholderPosition).setLoadMoreChildrenFailed(false); - placeholderTextView.setText(R.string.comment_load_more_comments); - - mVisibleComments.addAll(placeholderPosition, expandedComments); - if(mIsSingleCommentThreadMode) { - notifyItemRangeInserted(placeholderPosition + 2, expandedComments.size()); - } else { - notifyItemRangeInserted(placeholderPosition + 1, expandedComments.size()); - } - } else { - mVisibleComments.get(parentPosition).getChildren() - .remove(mVisibleComments.get(parentPosition).getChildren().size() - 1); - mVisibleComments.get(parentPosition).removeMoreChildrenFullnames(); - - int placeholderPosition = commentPosition; - if(mVisibleComments.get(commentPosition).getFullName().equals(parentComment.getFullName())) { - for(int i = parentPosition + 1; i < mVisibleComments.size(); i++) { - if(mVisibleComments.get(i).getFullName().equals(parentComment.getFullName())) { - placeholderPosition = i; - break; - } - } - } - - mVisibleComments.remove(placeholderPosition); - if(mIsSingleCommentThreadMode) { - notifyItemRemoved(placeholderPosition + 2); - } else { - notifyItemRemoved(placeholderPosition + 1); - } - - mVisibleComments.addAll(placeholderPosition, expandedComments); - if(mIsSingleCommentThreadMode) { - notifyItemRangeInserted(placeholderPosition + 2, expandedComments.size()); - } else { - notifyItemRangeInserted(placeholderPosition + 1, expandedComments.size()); - } - } - } else { - if(mVisibleComments.get(parentPosition).hasReply() && mVisibleComments.get(parentPosition).getChildren().size() <= childrenStartingIndex) { - mVisibleComments.get(parentPosition).getChildren() - .remove(mVisibleComments.get(parentPosition).getChildren().size() - 1); - mVisibleComments.get(parentPosition).removeMoreChildrenFullnames(); - } - } - - mVisibleComments.get(parentPosition).addChildren(expandedComments); - } else { - for(int i = 0; i < mVisibleComments.size(); i++) { - if(mVisibleComments.get(i).getFullName().equals(parentComment.getFullName())) { - if(mVisibleComments.get(i).isExpanded()) { - int placeholderPosition = i + mVisibleComments.get(i).getChildren().size(); - - if(!mVisibleComments.get(i).getFullName() - .equals(mVisibleComments.get(placeholderPosition).getFullName())) { - for(int j = i + 1; j < mVisibleComments.size(); j++) { - if(mVisibleComments.get(j).getFullName().equals(mVisibleComments.get(i).getFullName())) { - placeholderPosition = j; - } - } - } - - mVisibleComments.get(placeholderPosition).setLoadingMoreChildren(false); - mVisibleComments.get(placeholderPosition).setLoadMoreChildrenFailed(false); - placeholderTextView.setText(R.string.comment_load_more_comments); - - mVisibleComments.addAll(placeholderPosition, expandedComments); - if(mIsSingleCommentThreadMode) { - notifyItemRangeInserted(placeholderPosition + 2, expandedComments.size()); - } else { - notifyItemRangeInserted(placeholderPosition + 1, expandedComments.size()); - } - } - - mVisibleComments.get(i).getChildren().get(mVisibleComments.get(i).getChildren().size() - 1) - .setLoadingMoreChildren(false); - mVisibleComments.get(i).getChildren().get(mVisibleComments.get(i).getChildren().size() - 1) - .setLoadMoreChildrenFailed(false); - mVisibleComments.get(i).addChildren(expandedComments); - - break; - } - } - } - } - - @Override - public void onFetchMoreCommentFailed() { - if(parentPosition < mVisibleComments.size() - && parentComment.getFullName().equals(mVisibleComments.get(parentPosition).getFullName())) { - if(mVisibleComments.get(parentPosition).isExpanded()) { - int commentPosition = mIsSingleCommentThreadMode ? getAdapterPosition() - 2 : getAdapterPosition() - 1; - int placeholderPosition = commentPosition; - if(commentPosition >= mVisibleComments.size() || !mVisibleComments.get(commentPosition).getFullName().equals(parentComment.getFullName())) { - for(int i = parentPosition + 1; i < mVisibleComments.size(); i++) { - if(mVisibleComments.get(i).getFullName().equals(parentComment.getFullName())) { - placeholderPosition = i; - break; - } - } - } - - mVisibleComments.get(placeholderPosition).setLoadingMoreChildren(false); - mVisibleComments.get(placeholderPosition).setLoadMoreChildrenFailed(true); - placeholderTextView.setText(R.string.comment_load_more_comments_failed); - } - - mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1) - .setLoadingMoreChildren(false); - mVisibleComments.get(parentPosition).getChildren().get(mVisibleComments.get(parentPosition).getChildren().size() - 1) - .setLoadMoreChildrenFailed(true); - } else { - for(int i = 0; i < mVisibleComments.size(); i++) { - if(mVisibleComments.get(i).getFullName().equals(parentComment.getFullName())) { - if(mVisibleComments.get(i).isExpanded()) { - int placeholderPosition = i + mVisibleComments.get(i).getChildren().size(); - if(!mVisibleComments.get(placeholderPosition).getFullName().equals(mVisibleComments.get(i).getFullName())) { - for(int j = i + 1; j < mVisibleComments.size(); j++) { - if(mVisibleComments.get(j).getFullName().equals(mVisibleComments.get(i).getFullName())) { - placeholderPosition = j; - break; - } - } - } - - mVisibleComments.get(placeholderPosition).setLoadingMoreChildren(false); - mVisibleComments.get(placeholderPosition).setLoadMoreChildrenFailed(true); - placeholderTextView.setText(R.string.comment_load_more_comments_failed); - } - - mVisibleComments.get(i).getChildren().get(mVisibleComments.get(i).getChildren().size() - 1).setLoadingMoreChildren(false); - mVisibleComments.get(i).getChildren().get(mVisibleComments.get(i).getChildren().size() - 1).setLoadMoreChildrenFailed(true); - - break; - } - } - } - } - }); - }); - } - } - - class LoadCommentsViewHolder extends RecyclerView.ViewHolder { - LoadCommentsViewHolder(@NonNull View itemView) { - super(itemView); - } - } - - class LoadCommentsFailedViewHolder extends RecyclerView.ViewHolder { - LoadCommentsFailedViewHolder(@NonNull View itemView) { - super(itemView); - itemView.setOnClickListener(view -> { - mCommentRecyclerViewAdapterCallback.retryFetchingComments(); - }); - } - } - - class NoCommentViewHolder extends RecyclerView.ViewHolder { - NoCommentViewHolder(@NonNull View itemView) { - super(itemView); - } - } - - class IsLoadingMoreCommentsViewHolder extends RecyclerView.ViewHolder { - IsLoadingMoreCommentsViewHolder(@NonNull View itemView) { - super(itemView); - } - } - - class LoadMoreCommentsFailedViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.error_text_view_item_comment_footer_error) TextView errorTextView; - @BindView(R.id.retry_button_item_comment_footer_error) Button retryButton; - - LoadMoreCommentsFailedViewHolder(@NonNull View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - - retryButton.setOnClickListener(view -> mCommentRecyclerViewAdapterCallback.retryFetchingMoreComments()); - } - } - - class ViewAllCommentsViewHolder extends RecyclerView.ViewHolder { - - ViewAllCommentsViewHolder(@NonNull View itemView) { - super(itemView); - - itemView.setOnClickListener(view -> { - if(mActivity != null && mActivity instanceof ViewPostDetailActivity) { - mIsSingleCommentThreadMode = false; - mSingleCommentId = null; - ((ViewPostDetailActivity) mActivity).changeToSingleThreadMode(); - } - }); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentData.java index f936aac0..aeb85ce9 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentData.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentData.java @@ -5,10 +5,10 @@ import android.os.Parcelable; import java.util.ArrayList; -class CommentData implements Parcelable { - static final int VOTE_TYPE_NO_VOTE = 0; - static final int VOTE_TYPE_UPVOTE = 1; - static final int VOTE_TYPE_DOWNVOTE = -1; +public class CommentData implements Parcelable { + public static final int VOTE_TYPE_NO_VOTE = 0; + public static final int VOTE_TYPE_UPVOTE = 1; + public static final int VOTE_TYPE_DOWNVOTE = -1; private String id; private String fullName; @@ -38,7 +38,7 @@ class CommentData implements Parcelable { private boolean isLoadingMoreChildren; private boolean loadMoreChildrenFailed; - CommentData(String id, String fullName, String author, String linkAuthor, String commentTime, + public CommentData(String id, String fullName, String author, String linkAuthor, String commentTime, String commentContent, String linkId, String subredditName, String parentId, int score, int voteType, boolean isSubmitter, String distinguished, String permalink, int depth, boolean collapsed, boolean hasReply, boolean scoreHidden, boolean saved) { @@ -66,7 +66,7 @@ class CommentData implements Parcelable { isPlaceHolder = false; } - CommentData(String parentFullName, int depth) { + public CommentData(String parentFullName, int depth) { this.fullName = parentFullName; this.depth = depth; isPlaceHolder = true; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentViewModel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentViewModel.java index e5c4519d..6fc2d1c7 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentViewModel.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentViewModel.java @@ -48,31 +48,31 @@ public class CommentViewModel extends ViewModel { }); } - LiveData> getComments() { + public LiveData> getComments() { return comments; } - LiveData getPaginationNetworkState() { + public LiveData getPaginationNetworkState() { return paginationNetworkState; } - LiveData getInitialLoadingState() { + public LiveData getInitialLoadingState() { return initialLoadingState; } - LiveData hasComment() { + public LiveData hasComment() { return hasCommentLiveData; } - void refresh() { + public void refresh() { commentDataSourceFactory.getCommentDataSource().invalidate(); } - void retryLoadingMore() { + public void retryLoadingMore() { commentDataSourceFactory.getCommentDataSource().retryLoadingMore(); } - void changeSortType(String sortType) { + public void changeSortType(String sortType) { sortTypeLiveData.postValue(sortType); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentsListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentsListingFragment.java deleted file mode 100644 index e90e032d..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentsListingFragment.java +++ /dev/null @@ -1,216 +0,0 @@ -package ml.docilealligator.infinityforreddit; - - -import android.app.Activity; -import android.content.Context; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProvider; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import retrofit2.Retrofit; - - -/** - * A simple {@link Fragment} subclass. - */ -public class CommentsListingFragment extends Fragment implements FragmentCommunicator { - - static final String EXTRA_USERNAME = "EN"; - static final String EXTRA_ACCESS_TOKEN = "EAT"; - static final String EXTRA_ACCOUNT_NAME = "EAN"; - static final String EXTRA_ARE_SAVED_COMMENTS = "EISC"; - - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - - @BindView(R.id.coordinator_layout_comments_listing_fragment) CoordinatorLayout mCoordinatorLayout; - @BindView(R.id.recycler_view_comments_listing_fragment) RecyclerView mCommentRecyclerView; - @BindView(R.id.progress_bar_comments_listing_fragment) CircleProgressBar mProgressBar; - @BindView(R.id.fetch_comments_info_linear_layout_comments_listing_fragment) LinearLayout mFetchCommentInfoLinearLayout; - @BindView(R.id.fetch_comments_info_image_view_comments_listing_fragment) ImageView mFetchCommentInfoImageView; - @BindView(R.id.fetch_comments_info_text_view_comments_listing_fragment) TextView mFetchCommentInfoTextView; - - private boolean mNullAccessToken = false; - private String mAccessToken; - - private RequestManager mGlide; - - private Activity activity; - - private CommentsListingRecyclerViewAdapter mAdapter; - - CommentViewModel mCommentViewModel; - - @Inject - @Named("no_oauth") - Retrofit mRetrofit; - - @Inject @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - public CommentsListingFragment() { - // Required empty public constructor - } - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_comments_listing, container, false); - - ((Infinity) activity.getApplication()).getAppComponent().inject(this); - - ButterKnife.bind(this, rootView); - - mGlide = Glide.with(activity); - - Resources resources = getResources(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { - int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); - if (navBarResourceId > 0) { - mCommentRecyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); - } - } - } - - if (savedInstanceState == null) { - getCurrentAccountAndBindView(resources); - } else { - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - - if (!mNullAccessToken && mAccessToken == null) { - getCurrentAccountAndBindView(resources); - } else { - bindView(resources); - } - } - - return rootView; - } - - private void getCurrentAccountAndBindView(Resources resources) { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - } - bindView(resources); - }).execute(); - } - - private void bindView(Resources resources) { - mCommentRecyclerView.setLayoutManager(new LinearLayoutManager(activity)); - - mAdapter = new CommentsListingRecyclerViewAdapter(activity, mOauthRetrofit, - getArguments().getString(EXTRA_ACCESS_TOKEN), getArguments().getString(EXTRA_ACCOUNT_NAME), - () -> mCommentViewModel.retryLoadingMore()); - - String username = getArguments().getString(EXTRA_USERNAME); - - mCommentRecyclerView.setAdapter(mAdapter); - - CommentViewModel.Factory factory; - - if(mAccessToken == null) { - factory = new CommentViewModel.Factory(mRetrofit, - resources.getConfiguration().locale, mAccessToken, username, PostDataSource.SORT_TYPE_NEW, - getArguments().getBoolean(EXTRA_ARE_SAVED_COMMENTS)); - } else { - factory = new CommentViewModel.Factory(mOauthRetrofit, - resources.getConfiguration().locale, mAccessToken, username, PostDataSource.SORT_TYPE_NEW, - getArguments().getBoolean(EXTRA_ARE_SAVED_COMMENTS)); - } - - mCommentViewModel = new ViewModelProvider(this, factory).get(CommentViewModel.class); - mCommentViewModel.getComments().observe(this, comments -> mAdapter.submitList(comments)); - - mCommentViewModel.hasComment().observe(this, hasComment -> { - mProgressBar.setVisibility(View.GONE); - if(hasComment) { - mFetchCommentInfoLinearLayout.setVisibility(View.GONE); - } else { - mFetchCommentInfoLinearLayout.setOnClickListener(view -> { - //Do nothing - }); - showErrorView(R.string.no_comments); - } - }); - - mCommentViewModel.getInitialLoadingState().observe(this, networkState -> { - if(networkState.getStatus().equals(NetworkState.Status.SUCCESS)) { - mProgressBar.setVisibility(View.GONE); - } else if(networkState.getStatus().equals(NetworkState.Status.FAILED)) { - mProgressBar.setVisibility(View.GONE); - mFetchCommentInfoLinearLayout.setOnClickListener(view -> refresh()); - showErrorView(R.string.load_comments_failed); - } else { - mProgressBar.setVisibility(View.VISIBLE); - } - }); - - mCommentViewModel.getPaginationNetworkState().observe(this, networkState -> mAdapter.setNetworkState(networkState)); - } - - void changeSortType(String sortType) { - mCommentViewModel.changeSortType(sortType); - } - - @Override - public void onAttach(@NonNull Context context) { - super.onAttach(context); - this.activity = (Activity) context; - } - - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - } - - @Override - public void refresh() { - mFetchCommentInfoLinearLayout.setVisibility(View.GONE); - mCommentViewModel.refresh(); - mAdapter.setNetworkState(null); - } - - private void showErrorView(int stringResId) { - if(activity != null && isAdded()) { - mProgressBar.setVisibility(View.GONE); - mFetchCommentInfoLinearLayout.setVisibility(View.VISIBLE); - mFetchCommentInfoTextView.setText(stringResId); - mGlide.load(R.drawable.error_image).into(mFetchCommentInfoImageView); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentsListingRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentsListingRecyclerViewAdapter.java deleted file mode 100644 index eac2211b..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentsListingRecyclerViewAdapter.java +++ /dev/null @@ -1,427 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.text.util.Linkify; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.core.content.ContextCompat; -import androidx.paging.PagedListAdapter; -import androidx.recyclerview.widget.DiffUtil; -import androidx.recyclerview.widget.RecyclerView; - -import butterknife.BindView; -import butterknife.ButterKnife; -import io.noties.markwon.AbstractMarkwonPlugin; -import io.noties.markwon.Markwon; -import io.noties.markwon.MarkwonConfiguration; -import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.linkify.LinkifyPlugin; -import retrofit2.Retrofit; - -class CommentsListingRecyclerViewAdapter extends PagedListAdapter { - private Context mContext; - private Retrofit mOauthRetrofit; - private Markwon mMarkwon; - private String mAccessToken; - private String mAccountName; - private int mTextColorPrimaryDark; - private int mColorAccent; - - private static final int VIEW_TYPE_DATA = 0; - private static final int VIEW_TYPE_ERROR = 1; - private static final int VIEW_TYPE_LOADING = 2; - - private NetworkState networkState; - private RetryLoadingMoreCallback mRetryLoadingMoreCallback; - - interface RetryLoadingMoreCallback { - void retryLoadingMore(); - } - - protected CommentsListingRecyclerViewAdapter(Context context, Retrofit oauthRetrofit, - String accessToken, String accountName, - RetryLoadingMoreCallback retryLoadingMoreCallback) { - super(DIFF_CALLBACK); - mContext = context; - mOauthRetrofit = oauthRetrofit; - mMarkwon = Markwon.builder(mContext) - .usePlugin(new AbstractMarkwonPlugin() { - @Override - public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { - builder.linkResolver((view, link) -> { - Intent intent = new Intent(mContext, LinkResolverActivity.class); - Uri uri = Uri.parse(link); - if(uri.getScheme() == null && uri.getHost() == null) { - intent.setData(LinkResolverActivity.getRedditUriByPath(link)); - } else { - intent.setData(uri); - } - mContext.startActivity(intent); - }); - } - }) - .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) - .usePlugin(StrikethroughPlugin.create()) - .build(); - mAccessToken = accessToken; - mAccountName = accountName; - mRetryLoadingMoreCallback = retryLoadingMoreCallback; - mTextColorPrimaryDark = mContext.getResources().getColor(R.color.colorPrimaryDarkDayNightTheme); - mColorAccent = mContext.getResources().getColor(R.color.colorAccent); - } - - private static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() { - @Override - public boolean areItemsTheSame(@NonNull CommentData commentData, @NonNull CommentData t1) { - return commentData.getId().equals(t1.getId()); - } - - @Override - public boolean areContentsTheSame(@NonNull CommentData commentData, @NonNull CommentData t1) { - return commentData.getCommentContent().equals(t1.getCommentContent()); - } - }; - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - if(viewType == VIEW_TYPE_DATA) { - return new DataViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment, parent, false)); - } else if(viewType == VIEW_TYPE_ERROR) { - return new ErrorViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_error, parent, false)); - } else { - return new LoadingViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_loading, parent, false)); - } - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - if(holder instanceof DataViewHolder) { - CommentData comment = getItem(holder.getAdapterPosition()); - if(comment != null) { - if(comment.getSubredditName().substring(2).equals(comment.getLinkAuthor())) { - ((DataViewHolder) holder).authorTextView.setText("u/" + comment.getLinkAuthor()); - ((DataViewHolder) holder).authorTextView.setTextColor(mTextColorPrimaryDark); - ((DataViewHolder) holder).authorTextView.setOnClickListener(view -> { - Intent intent = new Intent(mContext, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, comment.getLinkAuthor()); - mContext.startActivity(intent); - }); - } else { - ((DataViewHolder) holder).authorTextView.setText("r/" + comment.getSubredditName()); - ((DataViewHolder) holder).authorTextView.setTextColor(mColorAccent); - ((DataViewHolder) holder).authorTextView.setOnClickListener(view -> { - Intent intent = new Intent(mContext, ViewSubredditDetailActivity.class); - intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, comment.getSubredditName()); - mContext.startActivity(intent); - }); - } - - ((DataViewHolder) holder).commentTimeTextView.setText(comment.getCommentTime()); - - mMarkwon.setMarkdown(((DataViewHolder) holder).commentMarkdownView, comment.getCommentContent()); - - ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType())); - - switch (comment.getVoteType()) { - case CommentData.VOTE_TYPE_UPVOTE: - ((DataViewHolder) holder).upvoteButton - .setColorFilter(ContextCompat.getColor(mContext, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.upvoted)); - break; - case CommentData.VOTE_TYPE_DOWNVOTE: - ((DataViewHolder) holder).downvoteButton - .setColorFilter(ContextCompat.getColor(mContext, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.downvoted)); - break; - } - - if(comment.getAuthor().equals(mAccountName)) { - ((DataViewHolder) holder).moreButton.setVisibility(View.VISIBLE); - ((DataViewHolder) holder).moreButton.setOnClickListener(view -> { - ModifyCommentBottomSheetFragment modifyCommentBottomSheetFragment = new ModifyCommentBottomSheetFragment(); - Bundle bundle = new Bundle(); - bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_COMMENT_CONTENT, comment.getCommentContent()); - bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_COMMENT_FULLNAME, comment.getFullName()); - bundle.putInt(ModifyCommentBottomSheetFragment.EXTRA_POSITION, holder.getAdapterPosition() - 1); - modifyCommentBottomSheetFragment.setArguments(bundle); - modifyCommentBottomSheetFragment.show(((AppCompatActivity) mContext).getSupportFragmentManager(), modifyCommentBottomSheetFragment.getTag()); - }); - } - - ((DataViewHolder) holder).linearLayout.setOnClickListener(view -> { - Intent intent = new Intent(mContext, ViewPostDetailActivity.class); - intent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, comment.getLinkId()); - intent.putExtra(ViewPostDetailActivity.EXTRA_SINGLE_COMMENT_ID, comment.getId()); - mContext.startActivity(intent); - }); - - ((DataViewHolder) holder).verticalBlock.setVisibility(View.GONE); - - ((DataViewHolder) holder).commentMarkdownView.setOnClickListener(view -> - ((DataViewHolder) holder).linearLayout.callOnClick()); - - ((DataViewHolder) holder).shareButton.setOnClickListener(view -> { - try { - Intent intent = new Intent(Intent.ACTION_SEND); - intent.setType("text/plain"); - String extraText = comment.getPermalink(); - intent.putExtra(Intent.EXTRA_TEXT, extraText); - mContext.startActivity(Intent.createChooser(intent, mContext.getString(R.string.share))); - } catch (ActivityNotFoundException e) { - Toast.makeText(mContext, R.string.no_activity_found_for_share, Toast.LENGTH_SHORT).show(); - } - }); - - ((DataViewHolder) holder).replyButton.setVisibility(View.GONE); - - ((DataViewHolder) holder).upvoteButton.setOnClickListener(view -> { - if(mAccessToken == null) { - Toast.makeText(mContext, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - int previousVoteType = comment.getVoteType(); - String newVoteType; - - ((DataViewHolder) holder).downvoteButton.clearColorFilter(); - - if(previousVoteType != CommentData.VOTE_TYPE_UPVOTE) { - //Not upvoted before - comment.setVoteType(CommentData.VOTE_TYPE_UPVOTE); - newVoteType = RedditUtils.DIR_UPVOTE; - ((DataViewHolder) holder).upvoteButton - .setColorFilter(ContextCompat.getColor(mContext, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.upvoted)); - } else { - //Upvoted before - comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); - newVoteType = RedditUtils.DIR_UNVOTE; - ((DataViewHolder) holder).upvoteButton.clearColorFilter(); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); - } - - ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType())); - - VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { - @Override - public void onVoteThingSuccess(int position) { - if(newVoteType.equals(RedditUtils.DIR_UPVOTE)) { - comment.setVoteType(CommentData.VOTE_TYPE_UPVOTE); - ((DataViewHolder) holder).upvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.upvoted)); - } else { - comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); - ((DataViewHolder) holder).upvoteButton.clearColorFilter(); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); - } - - ((DataViewHolder) holder).downvoteButton.clearColorFilter(); - ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType())); - } - - @Override - public void onVoteThingFail(int position) { } - }, comment.getFullName(), newVoteType, holder.getAdapterPosition()); - }); - - ((DataViewHolder) holder).downvoteButton.setOnClickListener(view -> { - if(mAccessToken == null) { - Toast.makeText(mContext, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - int previousVoteType = comment.getVoteType(); - String newVoteType; - - ((DataViewHolder) holder).upvoteButton.clearColorFilter(); - - if(previousVoteType != CommentData.VOTE_TYPE_DOWNVOTE) { - //Not downvoted before - comment.setVoteType(CommentData.VOTE_TYPE_DOWNVOTE); - newVoteType = RedditUtils.DIR_DOWNVOTE; - ((DataViewHolder) holder).downvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.downvoted)); - } else { - //Downvoted before - comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); - newVoteType = RedditUtils.DIR_UNVOTE; - ((DataViewHolder) holder).downvoteButton.clearColorFilter(); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); - } - - ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType())); - - VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { - @Override - public void onVoteThingSuccess(int position1) { - if(newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) { - comment.setVoteType(CommentData.VOTE_TYPE_DOWNVOTE); - ((DataViewHolder) holder).downvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.downvoted)); - } else { - comment.setVoteType(CommentData.VOTE_TYPE_NO_VOTE); - ((DataViewHolder) holder).downvoteButton.clearColorFilter(); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); - } - - ((DataViewHolder) holder).upvoteButton.clearColorFilter(); - ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(comment.getScore() + comment.getVoteType())); - } - - @Override - public void onVoteThingFail(int position1) { } - }, comment.getFullName(), newVoteType, holder.getAdapterPosition()); - }); - - if(comment.isSaved()) { - ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_20dp); - } else { - ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_20dp); - } - - ((DataViewHolder) holder).saveButton.setOnClickListener(view -> { - if (comment.isSaved()) { - comment.setSaved(false); - SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, comment.getFullName(), new SaveThing.SaveThingListener() { - @Override - public void success() { - comment.setSaved(false); - ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_20dp); - Toast.makeText(mContext, R.string.comment_unsaved_success, Toast.LENGTH_SHORT).show(); - } - - @Override - public void failed() { - comment.setSaved(true); - ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_20dp); - Toast.makeText(mContext, R.string.comment_unsaved_failed, Toast.LENGTH_SHORT).show(); - } - }); - } else { - comment.setSaved(true); - SaveThing.saveThing(mOauthRetrofit, mAccessToken, comment.getFullName(), new SaveThing.SaveThingListener() { - @Override - public void success() { - comment.setSaved(true); - ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_20dp); - Toast.makeText(mContext, R.string.comment_saved_success, Toast.LENGTH_SHORT).show(); - } - - @Override - public void failed() { - comment.setSaved(false); - ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_bookmark_border_20dp); - Toast.makeText(mContext, R.string.comment_saved_failed, Toast.LENGTH_SHORT).show(); - } - }); - } - }); - } - } - } - - @Override - public int getItemViewType(int position) { - // Reached at the end - if (hasExtraRow() && position == getItemCount() - 1) { - if (networkState.getStatus() == NetworkState.Status.LOADING) { - return VIEW_TYPE_LOADING; - } else { - return VIEW_TYPE_ERROR; - } - } else { - return VIEW_TYPE_DATA; - } - } - - @Override - public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { - if(holder instanceof DataViewHolder) { - ((DataViewHolder) holder).upvoteButton.clearColorFilter(); - ((DataViewHolder) holder).downvoteButton.clearColorFilter(); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); - } - } - - @Override - public int getItemCount() { - if(hasExtraRow()) { - return super.getItemCount() + 1; - } - return super.getItemCount(); - } - - private boolean hasExtraRow() { - return networkState != null && networkState.getStatus() != NetworkState.Status.SUCCESS; - } - - void setNetworkState(NetworkState newNetworkState) { - NetworkState previousState = this.networkState; - boolean previousExtraRow = hasExtraRow(); - this.networkState = newNetworkState; - boolean newExtraRow = hasExtraRow(); - if (previousExtraRow != newExtraRow) { - if (previousExtraRow) { - notifyItemRemoved(super.getItemCount()); - } else { - notifyItemInserted(super.getItemCount()); - } - } else if (newExtraRow && !previousState.equals(newNetworkState)) { - notifyItemChanged(getItemCount() - 1); - } - } - - class DataViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.linear_layout_item_comment) LinearLayout linearLayout; - @BindView(R.id.vertical_block_item_post_comment) View verticalBlock; - @BindView(R.id.author_text_view_item_post_comment) TextView authorTextView; - @BindView(R.id.comment_time_text_view_item_post_comment) TextView commentTimeTextView; - @BindView(R.id.comment_markdown_view_item_post_comment) TextView commentMarkdownView; - @BindView(R.id.up_vote_button_item_post_comment) ImageView upvoteButton; - @BindView(R.id.score_text_view_item_post_comment) TextView scoreTextView; - @BindView(R.id.down_vote_button_item_post_comment) ImageView downvoteButton; - @BindView(R.id.more_button_item_post_comment) ImageView moreButton; - @BindView(R.id.save_button_item_post_comment) ImageView saveButton; - @BindView(R.id.share_button_item_post_comment) ImageView shareButton; - @BindView(R.id.reply_button_item_post_comment) ImageView replyButton; - - DataViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - } - } - - class ErrorViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.error_text_view_item_footer_error) TextView errorTextView; - @BindView(R.id.retry_button_item_footer_error) Button retryButton; - - ErrorViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - errorTextView.setText(R.string.load_comments_failed); - retryButton.setOnClickListener(view -> mRetryLoadingMoreCallback.retryLoadingMore()); - } - } - - class LoadingViewHolder extends RecyclerView.ViewHolder { - LoadingViewHolder(@NonNull View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/DeleteThing.java b/app/src/main/java/ml/docilealligator/infinityforreddit/DeleteThing.java index e755e51f..69959679 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/DeleteThing.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/DeleteThing.java @@ -10,13 +10,13 @@ import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; -class DeleteThing { - interface DeleteThingListener { +public class DeleteThing { + public interface DeleteThingListener { void deleteSuccess(); void deleteFailed(); } - static void delete(Retrofit oauthRetrofit, String fullname, String accessToken, DeleteThingListener deleteThingListener) { + public static void delete(Retrofit oauthRetrofit, String fullname, String accessToken, DeleteThingListener deleteThingListener) { Map params = new HashMap<>(); params.put(RedditUtils.ID_KEY, fullname); oauthRetrofit.create(RedditAPI.class).delete(RedditUtils.getOAuthHeader(accessToken), params).enqueue(new Callback() { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/EditCommentActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/EditCommentActivity.java deleted file mode 100644 index 242d6315..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/EditCommentActivity.java +++ /dev/null @@ -1,208 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.view.inputmethod.InputMethodManager; -import android.widget.EditText; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.core.content.ContextCompat; - -import com.google.android.material.snackbar.Snackbar; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import java.util.HashMap; -import java.util.Map; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class EditCommentActivity extends AppCompatActivity { - - static final String EXTRA_CONTENT = "EC"; - static final String EXTRA_FULLNAME = "EF"; - static final String EXTRA_ACCESS_TOKEN = "EAT"; - static final String EXTRA_POSITION = "EP"; - - static final String EXTRA_EDITED_COMMENT_CONTENT = "EECC"; - static final String EXTRA_EDITED_COMMENT_POSITION = "EECP"; - - @BindView(R.id.coordinator_layout_edit_comment_activity) CoordinatorLayout coordinatorLayout; - @BindView(R.id.toolbar_edit_comment_activity) Toolbar toolbar; - @BindView(R.id.post_text_content_edit_text_edit_comment_activity) EditText contentEditText; - - private String mFullName; - private String mAccessToken; - private boolean isSubmitting = false; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_edit_comment); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - Window window = getWindow(); - if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - mFullName = getIntent().getExtras().getString(EXTRA_FULLNAME); - mAccessToken = getIntent().getExtras().getString(EXTRA_ACCESS_TOKEN); - contentEditText.setText(getIntent().getExtras().getString(EXTRA_CONTENT)); - - contentEditText.requestFocus(); - InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - if(imm != null) { - imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); - } - } - - @Override - protected void onPause() { - super.onPause(); - InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); - if(imm != null) { - imm.hideSoftInputFromWindow(contentEditText.getWindowToken(), 0); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.edit_comment_activity, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if(item.getItemId() == R.id.action_send_edit_comment_activity) { - if(!isSubmitting) { - isSubmitting = true; - - Snackbar.make(coordinatorLayout, R.string.posting, Snackbar.LENGTH_SHORT).show(); - - String content = contentEditText.getText().toString(); - - Map params = new HashMap<>(); - params.put(RedditUtils.THING_ID_KEY, mFullName); - params.put(RedditUtils.TEXT_KEY, content); - - mOauthRetrofit.create(RedditAPI.class) - .editPostOrComment(RedditUtils.getOAuthHeader(mAccessToken), params) - .enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - isSubmitting = false; - if(response.isSuccessful()) { - Toast.makeText(EditCommentActivity.this, R.string.edit_success, Toast.LENGTH_SHORT).show(); - - Intent returnIntent = new Intent(); - returnIntent.putExtra(EXTRA_EDITED_COMMENT_CONTENT, content); - returnIntent.putExtra(EXTRA_EDITED_COMMENT_POSITION, getIntent().getExtras().getInt(EXTRA_POSITION)); - setResult(RESULT_OK, returnIntent); - - finish(); - } else { - Snackbar.make(coordinatorLayout, R.string.post_failed, Snackbar.LENGTH_SHORT).show(); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - isSubmitting = false; - Snackbar.make(coordinatorLayout, R.string.post_failed, Snackbar.LENGTH_SHORT).show(); - } - }); - - } - return true; - } else if(item.getItemId() == android.R.id.home) { - finish(); - return true; - } - return false; - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/EditPostActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/EditPostActivity.java deleted file mode 100644 index dc2a755b..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/EditPostActivity.java +++ /dev/null @@ -1,198 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.view.inputmethod.InputMethodManager; -import android.widget.EditText; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.core.content.ContextCompat; - -import com.google.android.material.snackbar.Snackbar; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import java.util.HashMap; -import java.util.Map; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class EditPostActivity extends AppCompatActivity { - - static final String EXTRA_TITLE = "ET"; - static final String EXTRA_CONTENT = "EC"; - static final String EXTRA_FULLNAME = "EF"; - static final String EXTRA_ACCESS_TOKEN = "EAT"; - - @BindView(R.id.coordinator_layout_edit_post_activity) CoordinatorLayout coordinatorLayout; - @BindView(R.id.toolbar_edit_post_activity) Toolbar toolbar; - @BindView(R.id.post_title_text_view_edit_post_activity) TextView titleTextView; - @BindView(R.id.post_text_content_edit_text_edit_post_activity) EditText contentEditText; - - private String mFullName; - private String mAccessToken; - private boolean isSubmitting = false; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_edit_post); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - Window window = getWindow(); - if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - mFullName = getIntent().getExtras().getString(EXTRA_FULLNAME); - mAccessToken = getIntent().getExtras().getString(EXTRA_ACCESS_TOKEN); - titleTextView.setText(getIntent().getExtras().getString(EXTRA_TITLE)); - contentEditText.setText(getIntent().getExtras().getString(EXTRA_CONTENT)); - - contentEditText.requestFocus(); - InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - if(imm != null) { - imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); - } - } - - @Override - protected void onPause() { - super.onPause(); - InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); - if(imm != null) { - imm.hideSoftInputFromWindow(contentEditText.getWindowToken(), 0); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.edit_post_activity, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if(item.getItemId() == R.id.action_send_edit_post_activity) { - if(!isSubmitting) { - isSubmitting = true; - - Snackbar.make(coordinatorLayout, R.string.posting, Snackbar.LENGTH_SHORT).show(); - - Map params = new HashMap<>(); - params.put(RedditUtils.THING_ID_KEY, mFullName); - params.put(RedditUtils.TEXT_KEY, contentEditText.getText().toString()); - - mOauthRetrofit.create(RedditAPI.class) - .editPostOrComment(RedditUtils.getOAuthHeader(mAccessToken), params) - .enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - isSubmitting = false; - Toast.makeText(EditPostActivity.this, R.string.edit_success, Toast.LENGTH_SHORT).show(); - Intent returnIntent = new Intent(); - setResult(RESULT_OK, returnIntent); - finish(); - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - isSubmitting = false; - Snackbar.make(coordinatorLayout, R.string.post_failed, Snackbar.LENGTH_SHORT).show(); - } - }); - - } - return true; - } else if(item.getItemId() == android.R.id.home) { - finish(); - return true; - } - return false; - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeFontSizeEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeFontSizeEvent.java new file mode 100644 index 00000000..3dc4575e --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeFontSizeEvent.java @@ -0,0 +1,3 @@ +package ml.docilealligator.infinityforreddit.Event; + +public class ChangeFontSizeEvent { } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeNSFWBlurEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeNSFWBlurEvent.java new file mode 100644 index 00000000..c2145f16 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeNSFWBlurEvent.java @@ -0,0 +1,8 @@ +package ml.docilealligator.infinityforreddit.Event; + +public class ChangeNSFWBlurEvent { + public boolean needBlurNSFW; + public ChangeNSFWBlurEvent(boolean needBlurNSFW) { + this.needBlurNSFW = needBlurNSFW; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeNSFWEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeNSFWEvent.java new file mode 100644 index 00000000..db261f52 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeNSFWEvent.java @@ -0,0 +1,8 @@ +package ml.docilealligator.infinityforreddit.Event; + +public class ChangeNSFWEvent { + public boolean nsfw; + public ChangeNSFWEvent(boolean nsfw) { + this.nsfw = nsfw; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeSpoilerBlurEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeSpoilerBlurEvent.java new file mode 100644 index 00000000..a0fde8a2 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/ChangeSpoilerBlurEvent.java @@ -0,0 +1,8 @@ +package ml.docilealligator.infinityforreddit.Event; + +public class ChangeSpoilerBlurEvent { + public boolean needBlurSpoiler; + public ChangeSpoilerBlurEvent(boolean needBlurSpoiler) { + this.needBlurSpoiler = needBlurSpoiler; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Event/PostUpdateEventToDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/PostUpdateEventToDetailActivity.java new file mode 100644 index 00000000..0d502aa6 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/PostUpdateEventToDetailActivity.java @@ -0,0 +1,11 @@ +package ml.docilealligator.infinityforreddit.Event; + +import ml.docilealligator.infinityforreddit.Post; + +public class PostUpdateEventToDetailActivity { + public final Post post; + + public PostUpdateEventToDetailActivity(Post post) { + this.post = post; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Event/PostUpdateEventToPostList.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/PostUpdateEventToPostList.java new file mode 100644 index 00000000..10dadb7d --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/PostUpdateEventToPostList.java @@ -0,0 +1,13 @@ +package ml.docilealligator.infinityforreddit.Event; + +import ml.docilealligator.infinityforreddit.Post; + +public class PostUpdateEventToPostList { + public final Post post; + public final int positionInList; + + public PostUpdateEventToPostList(Post post, int positionInList) { + this.post = post; + this.positionInList = positionInList; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Event/SubmitImagePostEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/SubmitImagePostEvent.java new file mode 100644 index 00000000..7c0f5064 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/SubmitImagePostEvent.java @@ -0,0 +1,11 @@ +package ml.docilealligator.infinityforreddit.Event; + +public class SubmitImagePostEvent { + public boolean postSuccess; + public String errorMessage; + + public SubmitImagePostEvent(boolean postSuccess, String errorMessage) { + this.postSuccess = postSuccess; + this.errorMessage = errorMessage; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Event/SubmitTextOrLinkPostEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/SubmitTextOrLinkPostEvent.java new file mode 100644 index 00000000..3d43664e --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/SubmitTextOrLinkPostEvent.java @@ -0,0 +1,15 @@ +package ml.docilealligator.infinityforreddit.Event; + +import ml.docilealligator.infinityforreddit.Post; + +public class SubmitTextOrLinkPostEvent { + public boolean postSuccess; + public Post post; + public String errorMessage; + + public SubmitTextOrLinkPostEvent(boolean postSuccess, Post post, String errorMessage) { + this.postSuccess = postSuccess; + this.post = post; + this.errorMessage = errorMessage; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Event/SubmitVideoPostEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/SubmitVideoPostEvent.java new file mode 100644 index 00000000..e30cb0e1 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/SubmitVideoPostEvent.java @@ -0,0 +1,13 @@ +package ml.docilealligator.infinityforreddit.Event; + +public class SubmitVideoPostEvent { + public boolean postSuccess; + public boolean errorProcessingVideo; + public String errorMessage; + + public SubmitVideoPostEvent(boolean postSuccess, boolean errorProcessingVideo, String errorMessage) { + this.postSuccess = postSuccess; + this.errorProcessingVideo = errorProcessingVideo; + this.errorMessage = errorMessage; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Event/SwitchAccountEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/SwitchAccountEvent.java new file mode 100644 index 00000000..93068e71 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/SwitchAccountEvent.java @@ -0,0 +1,9 @@ +package ml.docilealligator.infinityforreddit.Event; + +public class SwitchAccountEvent { + public String excludeActivityClassName; + public SwitchAccountEvent() {} + public SwitchAccountEvent(String excludeActivityClassName) { + this.excludeActivityClassName = excludeActivityClassName; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java index f3ac4944..caa0c82c 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java @@ -11,19 +11,19 @@ import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; -class FetchComment { - interface FetchCommentListener { +public class FetchComment { + public interface FetchCommentListener { void onFetchCommentSuccess(ArrayList expandedComments, String parentId, ArrayList children); void onFetchCommentFailed(); } - interface FetchMoreCommentListener { + public interface FetchMoreCommentListener { void onFetchMoreCommentSuccess(ArrayList expandedComments, int childrenStartingIndex); void onFetchMoreCommentFailed(); } - static void fetchComments(Retrofit retrofit, @Nullable String accessToken, String article, String commentId, - Locale locale, FetchCommentListener fetchCommentListener) { + public static void fetchComments(Retrofit retrofit, @Nullable String accessToken, String article, String commentId, + Locale locale, FetchCommentListener fetchCommentListener) { RedditAPI api = retrofit.create(RedditAPI.class); Call comments; if(accessToken == null) { @@ -70,9 +70,9 @@ class FetchComment { }); } - static void fetchMoreComment(Retrofit retrofit, @Nullable String accessToken, - ArrayList allChildren, int startingIndex, - int depth, Locale locale, FetchMoreCommentListener fetchMoreCommentListener) { + public static void fetchMoreComment(Retrofit retrofit, @Nullable String accessToken, + ArrayList allChildren, int startingIndex, + int depth, Locale locale, FetchMoreCommentListener fetchMoreCommentListener) { StringBuilder stringBuilder = new StringBuilder(); for(int i = 0; i < 100; i++) { if(allChildren.size() <= startingIndex + i) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchFlairs.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchFlairs.java index 073067d2..946db033 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchFlairs.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchFlairs.java @@ -14,13 +14,13 @@ import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; -class FetchFlairs { - interface FetchFlairsInSubredditListener { +public class FetchFlairs { + public interface FetchFlairsInSubredditListener { void fetchSuccessful(ArrayList flairs); void fetchFailed(); } - static void fetchFlairsInSubreddit(Retrofit oauthRetrofit, String accessToken, String subredditName, FetchFlairsInSubredditListener fetchFlairsInSubredditListener) { + public static void fetchFlairsInSubreddit(Retrofit oauthRetrofit, String accessToken, String subredditName, FetchFlairsInSubredditListener fetchFlairsInSubredditListener) { RedditAPI api = oauthRetrofit.create(RedditAPI.class); Call flairsCall = api.getFlairs(RedditUtils.getOAuthHeader(accessToken), subredditName); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchMessages.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchMessages.java index bc738b83..00611210 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchMessages.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchMessages.java @@ -19,17 +19,17 @@ import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; -class FetchMessages { +public class FetchMessages { interface FetchMessagesListener { void fetchSuccess(ArrayList messages, @Nullable String after); void fetchFailed(); } - static final String WHERE_INBOX = "inbox"; - static final String WHERE_UNREAD = "unread"; - static final String WHERE_SENT = "sent"; - static final String WHERE_COMMENTS = "comments"; + public static final String WHERE_INBOX = "inbox"; + public static final String WHERE_UNREAD = "unread"; + public static final String WHERE_SENT = "sent"; + public static final String WHERE_COMMENTS = "comments"; static void fetchMessagesAsync(Retrofit oauthRetrofit, Locale locale, String accessToken, String where, String after, FetchMessagesListener fetchMessagesListener) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchMyInfo.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchMyInfo.java index 1538a70e..644c78a2 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchMyInfo.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchMyInfo.java @@ -8,15 +8,15 @@ import retrofit2.Call; import retrofit2.Callback; import retrofit2.Retrofit; -class FetchMyInfo { +public class FetchMyInfo { - interface FetchUserMyListener { + public interface FetchUserMyListener { void onFetchMyInfoSuccess(String response); void onFetchMyInfoFail(); } - static void fetchAccountInfo(final Retrofit retrofit, String accessToken, - final FetchUserMyListener fetchUserMyListener) { + public static void fetchAccountInfo(final Retrofit retrofit, String accessToken, + final FetchUserMyListener fetchUserMyListener) { RedditAPI api = retrofit.create(RedditAPI.class); Call userInfo = api.getMyInfo(RedditUtils.getOAuthHeader(accessToken)); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchPost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchPost.java index 02901768..fa6c7891 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchPost.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchPost.java @@ -9,13 +9,13 @@ import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; -class FetchPost { - interface FetchPostListener { +public class FetchPost { + public interface FetchPostListener { void fetchPostSuccess(Post post); void fetchPostFailed(); } - static void fetchPost(Retrofit retrofit, String id, String accessToken, Locale locale, FetchPostListener fetchPostListener) { + public static void fetchPost(Retrofit retrofit, String id, String accessToken, Locale locale, FetchPostListener fetchPostListener) { Call postCall; if(accessToken == null) { postCall = retrofit.create(RedditAPI.class).getPost(id); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubredditData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubredditData.java index 696a2dd6..bbb485cf 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubredditData.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubredditData.java @@ -10,8 +10,8 @@ import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; -class FetchSubredditData { - interface FetchSubredditDataListener { +public class FetchSubredditData { + public interface FetchSubredditDataListener { void onFetchSubredditDataSuccess(SubredditData subredditData, int nCurrentOnlineSubscribers); void onFetchSubredditDataFail(); } @@ -21,7 +21,7 @@ class FetchSubredditData { void onFetchSubredditListingDataFail(); } - static void fetchSubredditData(Retrofit retrofit, String subredditName, final FetchSubredditDataListener fetchSubredditDataListener) { + public static void fetchSubredditData(Retrofit retrofit, String subredditName, final FetchSubredditDataListener fetchSubredditDataListener) { RedditAPI api = retrofit.create(RedditAPI.class); Call subredditData = api.getSubredditData(subredditName); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubscribedThing.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubscribedThing.java index d1a6977b..52fd2c66 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubscribedThing.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubscribedThing.java @@ -12,19 +12,19 @@ import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; -class FetchSubscribedThing { - interface FetchSubscribedThingListener { +public class FetchSubscribedThing { + public interface FetchSubscribedThingListener { void onFetchSubscribedThingSuccess(ArrayList subscribedSubredditData, ArrayList subscribedUserData, ArrayList subredditData); void onFetchSubscribedThingFail(); } - static void fetchSubscribedThing(final Retrofit retrofit, String accessToken, String accountName, - final String lastItem, final ArrayList subscribedSubredditData, - final ArrayList subscribedUserData, - final ArrayList subredditData, - final FetchSubscribedThingListener fetchSubscribedThingListener) { + public static void fetchSubscribedThing(final Retrofit retrofit, String accessToken, String accountName, + final String lastItem, final ArrayList subscribedSubredditData, + final ArrayList subscribedUserData, + final ArrayList subredditData, + final FetchSubscribedThingListener fetchSubscribedThingListener) { RedditAPI api = retrofit.create(RedditAPI.class); Call subredditDataCall = api.getSubscribedThing(lastItem, RedditUtils.getOAuthHeader(accessToken)); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FilteredThingActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FilteredThingActivity.java deleted file mode 100644 index d4e67189..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FilteredThingActivity.java +++ /dev/null @@ -1,385 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.fragment.app.Fragment; - -import com.google.android.material.appbar.AppBarLayout; -import com.google.android.material.appbar.CollapsingToolbarLayout; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import javax.inject.Inject; - -import butterknife.BindView; -import butterknife.ButterKnife; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class FilteredThingActivity extends AppCompatActivity implements SortTypeBottomSheetFragment.SortTypeSelectionCallback, - SearchPostSortTypeBottomSheetFragment.SearchSortTypeSelectionCallback, UserThingSortTypeBottomSheetFragment.UserThingSortTypeSelectionCallback { - - static final String EXTRA_NAME = "ESN"; - static final String EXTRA_QUERY = "EQ"; - static final String EXTRA_FILTER = "EF"; - static final String EXTRA_POST_TYPE = "EPT"; - static final String EXTRA_SORT_TYPE = "EST"; - static final String EXTRA_USER_WHERE = "EUW"; - - private static final String IS_IN_LAZY_MODE_STATE = "IILMS"; - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - private static final String FRAGMENT_OUT_STATE = "FOS"; - - @BindView(R.id.appbar_layout_filtered_posts_activity) AppBarLayout appBarLayout; - @BindView(R.id.collapsing_toolbar_layout_filtered_posts_activity) CollapsingToolbarLayout collapsingToolbarLayout; - @BindView(R.id.toolbar_filtered_posts_activity) Toolbar toolbar; - - private boolean isInLazyMode = false; - private boolean mNullAccessToken = false; - private String mAccessToken; - private String name; - private int postType; - - private Fragment mFragment; - private Menu mMenu; - private AppBarLayout.LayoutParams params; - - private SortTypeBottomSheetFragment bestSortTypeBottomSheetFragment; - private SortTypeBottomSheetFragment popularAndAllSortTypeBottomSheetFragment; - private SortTypeBottomSheetFragment subredditSortTypeBottomSheetFragment; - private UserThingSortTypeBottomSheetFragment userThingSortTypeBottomSheetFragment; - private SearchPostSortTypeBottomSheetFragment searchPostSortTypeBottomSheetFragment; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_filtered_thing); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - Resources resources = getResources(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 - && (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT - || resources.getBoolean(R.bool.isTablet))) { - Window window = getWindow(); - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - - boolean lightNavBar = false; - if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - lightNavBar = true; - } - boolean finalLightNavBar = lightNavBar; - - View decorView = window.getDecorView(); - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { - @Override - void onStateChanged(AppBarLayout appBarLayout, State state) { - if (state == State.COLLAPSED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } else if (state == State.EXPANDED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } - } - }); - - int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); - if (statusBarResourceId > 0) { - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); - params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); - toolbar.setLayoutParams(params); - } - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); - - name = getIntent().getStringExtra(EXTRA_NAME); - postType = getIntent().getIntExtra(EXTRA_POST_TYPE, PostDataSource.TYPE_FRONT_PAGE); - int filter = getIntent().getIntExtra(EXTRA_FILTER, Post.TEXT_TYPE); - String sortType = getIntent().getStringExtra(EXTRA_SORT_TYPE); - - if(savedInstanceState != null) { - isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - if(!mNullAccessToken && mAccessToken == null) { - getCurrentAccountAndBindView(filter, sortType); - } else { - mFragment = getSupportFragmentManager().getFragment(savedInstanceState, FRAGMENT_OUT_STATE); - getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_filtered_posts_activity, mFragment).commit(); - bindView(filter, sortType, false); - } - } else { - getCurrentAccountAndBindView(filter, sortType); - } - } - - private void getCurrentAccountAndBindView(int filter, String sortType) { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - } - bindView(filter, sortType, true); - }).execute(); - } - - private void bindView(int filter, String sortType, boolean initializeFragment) { - switch (postType) { - case PostDataSource.TYPE_FRONT_PAGE: - getSupportActionBar().setTitle(name); - - bestSortTypeBottomSheetFragment = new SortTypeBottomSheetFragment(); - Bundle bestBundle = new Bundle(); - bestBundle.putBoolean(SortTypeBottomSheetFragment.EXTRA_NO_BEST_TYPE, false); - bestSortTypeBottomSheetFragment.setArguments(bestBundle); - break; - case PostDataSource.TYPE_SEARCH: - getSupportActionBar().setTitle(R.string.search); - - searchPostSortTypeBottomSheetFragment = new SearchPostSortTypeBottomSheetFragment(); - Bundle searchBundle = new Bundle(); - searchPostSortTypeBottomSheetFragment.setArguments(searchBundle); - break; - case PostDataSource.TYPE_SUBREDDIT: - if(name.equals("popular") || name.equals("all")) { - getSupportActionBar().setTitle(name.substring(0, 1).toUpperCase() + name.substring(1)); - - popularAndAllSortTypeBottomSheetFragment = new SortTypeBottomSheetFragment(); - Bundle popularBundle = new Bundle(); - popularBundle.putBoolean(SortTypeBottomSheetFragment.EXTRA_NO_BEST_TYPE, true); - popularAndAllSortTypeBottomSheetFragment.setArguments(popularBundle); - } else { - String subredditNamePrefixed = "r/" + name; - getSupportActionBar().setTitle(subredditNamePrefixed); - - subredditSortTypeBottomSheetFragment = new SortTypeBottomSheetFragment(); - Bundle bottomSheetBundle = new Bundle(); - bottomSheetBundle.putBoolean(SortTypeBottomSheetFragment.EXTRA_NO_BEST_TYPE, true); - subredditSortTypeBottomSheetFragment.setArguments(bottomSheetBundle); - } - break; - case PostDataSource.TYPE_USER: - String usernamePrefixed = "u/" + name; - getSupportActionBar().setTitle(usernamePrefixed); - - userThingSortTypeBottomSheetFragment = new UserThingSortTypeBottomSheetFragment(); - break; - } - - switch (filter) { - case Post.NSFW_TYPE: - toolbar.setSubtitle(R.string.nsfw); - break; - case Post.TEXT_TYPE: - toolbar.setSubtitle(R.string.text); - break; - case Post.LINK_TYPE: - case Post.NO_PREVIEW_LINK_TYPE: - toolbar.setSubtitle(R.string.link); - break; - case Post.IMAGE_TYPE: - toolbar.setSubtitle(R.string.image); - break; - case Post.VIDEO_TYPE: - toolbar.setSubtitle(R.string.video); - break; - case Post.GIF_VIDEO_TYPE: - toolbar.setSubtitle(R.string.gif); - } - - if(initializeFragment) { - mFragment = new PostFragment(); - Bundle bundle = new Bundle(); - bundle.putString(PostFragment.EXTRA_NAME, name); - bundle.putInt(PostFragment.EXTRA_POST_TYPE, postType); - bundle.putString(PostFragment.EXTRA_SORT_TYPE, sortType); - bundle.putInt(PostFragment.EXTRA_FILTER, filter); - bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - if(postType == PostDataSource.TYPE_USER) { - bundle.putString(PostFragment.EXTRA_USER_WHERE, getIntent().getStringExtra(EXTRA_USER_WHERE)); - } - if(postType == PostDataSource.TYPE_SEARCH) { - bundle.putString(PostFragment.EXTRA_QUERY, getIntent().getStringExtra(EXTRA_QUERY)); - } - mFragment.setArguments(bundle); - getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_filtered_posts_activity, mFragment).commit(); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.filtered_posts_activity, menu); - mMenu = menu; - MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_filtered_thing_activity); - if(isInLazyMode) { - lazyModeItem.setTitle(R.string.action_stop_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); - collapsingToolbarLayout.setLayoutParams(params); - } else { - lazyModeItem.setTitle(R.string.action_start_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); - collapsingToolbarLayout.setLayoutParams(params); - } - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; - case R.id.action_sort_filtered_thing_activity: - switch (postType) { - case PostDataSource.TYPE_FRONT_PAGE: - bestSortTypeBottomSheetFragment.show(getSupportFragmentManager(), bestSortTypeBottomSheetFragment.getTag()); - break; - case PostDataSource.TYPE_SEARCH: - searchPostSortTypeBottomSheetFragment.show(getSupportFragmentManager(), searchPostSortTypeBottomSheetFragment.getTag()); - break; - case PostDataSource.TYPE_SUBREDDIT: - if(name.equals("popular") || name.equals("all")) { - popularAndAllSortTypeBottomSheetFragment.show(getSupportFragmentManager(), popularAndAllSortTypeBottomSheetFragment.getTag()); - } else { - subredditSortTypeBottomSheetFragment.show(getSupportFragmentManager(), subredditSortTypeBottomSheetFragment.getTag()); - } - break; - case PostDataSource.TYPE_USER: - userThingSortTypeBottomSheetFragment.show(getSupportFragmentManager(), userThingSortTypeBottomSheetFragment.getTag()); - } - return true; - case R.id.action_refresh_filtered_thing_activity: - if(mMenu != null) { - mMenu.findItem(R.id.action_lazy_mode_filtered_thing_activity).setTitle(R.string.action_start_lazy_mode); - } - if(mFragment instanceof FragmentCommunicator) { - ((FragmentCommunicator) mFragment).refresh(); - } - return true; - case R.id.action_lazy_mode_filtered_thing_activity: - MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_filtered_thing_activity); - if(isInLazyMode) { - ((FragmentCommunicator) mFragment).stopLazyMode(); - isInLazyMode = false; - lazyModeItem.setTitle(R.string.action_start_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); - collapsingToolbarLayout.setLayoutParams(params); - } else { - if(((FragmentCommunicator) mFragment).startLazyMode()) { - isInLazyMode = true; - lazyModeItem.setTitle(R.string.action_stop_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); - collapsingToolbarLayout.setLayoutParams(params); - } - } - return true; - } - return false; - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - if (mFragment != null) { - getSupportFragmentManager().putFragment(outState, FRAGMENT_OUT_STATE, mFragment); - } - outState.putBoolean(IS_IN_LAZY_MODE_STATE, isInLazyMode); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - @Override - public void searchSortTypeSelected(String sortType) { - ((PostFragment)mFragment).changeSortType(sortType); - } - - @Override - public void sortTypeSelected(String sortType) { - ((PostFragment)mFragment).changeSortType(sortType); - } - - @Override - public void userThingSortTypeSelected(String sortType) { - ((PostFragment)mFragment).changeSortType(sortType); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Flair.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Flair.java index e60566ce..88ec4d90 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Flair.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Flair.java @@ -3,7 +3,7 @@ package ml.docilealligator.infinityforreddit; import android.os.Parcel; import android.os.Parcelable; -class Flair implements Parcelable { +public class Flair implements Parcelable { private String id; private String text; private boolean editable; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FlairBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FlairBottomSheetFragment.java deleted file mode 100644 index 6087e350..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FlairBottomSheetFragment.java +++ /dev/null @@ -1,120 +0,0 @@ -package ml.docilealligator.infinityforreddit; - - -import android.app.Activity; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ProgressBar; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.google.android.material.bottomsheet.BottomSheetDialogFragment; - -import java.util.ArrayList; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import retrofit2.Retrofit; - - -/** - * A simple {@link Fragment} subclass. - */ -public class FlairBottomSheetFragment extends BottomSheetDialogFragment { - - interface FlairSelectionCallback { - void flairSelected(Flair flair); - } - - static final String EXTRA_ACCESS_TOKEN = "EAT"; - static final String EXTRA_SUBREDDIT_NAME = "ESN"; - - @BindView(R.id.progress_bar_flair_bottom_sheet_fragment) ProgressBar progressBar; - @BindView(R.id.error_text_view_flair_bottom_sheet_fragment) TextView errorTextView; - @BindView(R.id.recycler_view_bottom_sheet_fragment) RecyclerView recyclerView; - - private String mAccessToken; - private String mSubredditName; - - private Activity mActivity; - private FlairBottomSheetRecyclerViewAdapter mAdapter; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - @Named("no_oauth") - Retrofit mRetrofit; - - public FlairBottomSheetFragment() { - // Required empty public constructor - } - - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_flair_bottom_sheet, container, false); - - ButterKnife.bind(this, rootView); - - mActivity = getActivity(); - - ((Infinity) mActivity.getApplication()).getAppComponent().inject(this); - - /*if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O - && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - }*/ - - mAdapter = new FlairBottomSheetRecyclerViewAdapter(mActivity, flair -> { - ((FlairSelectionCallback) mActivity).flairSelected(flair); - dismiss(); - }); - - recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); - recyclerView.setAdapter(mAdapter); - - mAccessToken = getArguments().getString(EXTRA_ACCESS_TOKEN); - mSubredditName = getArguments().getString(EXTRA_SUBREDDIT_NAME); - - fetchFlairs(); - - return rootView; - } - - private void fetchFlairs() { - FetchFlairs.fetchFlairsInSubreddit(mOauthRetrofit, mAccessToken, - mSubredditName, new FetchFlairs.FetchFlairsInSubredditListener() { - @Override - public void fetchSuccessful(ArrayList flairs) { - progressBar.setVisibility(View.GONE); - if(flairs == null || flairs.size() == 0) { - errorTextView.setVisibility(View.VISIBLE); - errorTextView.setText(R.string.no_flair); - } else { - errorTextView.setVisibility(View.GONE); - mAdapter.changeDataset(flairs); - } - } - - @Override - public void fetchFailed() { - progressBar.setVisibility(View.GONE); - errorTextView.setVisibility(View.VISIBLE); - errorTextView.setText(R.string.error_loading_flairs); - errorTextView.setOnClickListener(view -> fetchFlairs()); - } - }); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FlairBottomSheetRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FlairBottomSheetRecyclerViewAdapter.java deleted file mode 100644 index d1eecf20..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FlairBottomSheetRecyclerViewAdapter.java +++ /dev/null @@ -1,105 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.app.Activity; -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.inputmethod.InputMethodManager; -import android.widget.EditText; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; - -import com.google.android.material.dialog.MaterialAlertDialogBuilder; - -import java.util.ArrayList; - -import butterknife.BindView; -import butterknife.ButterKnife; - -class FlairBottomSheetRecyclerViewAdapter extends RecyclerView.Adapter { - interface ItemClickListener { - void onClick(Flair flair); - } - - private Context context; - private ArrayList flairs; - private ItemClickListener itemClickListener; - - FlairBottomSheetRecyclerViewAdapter(Context context, ItemClickListener itemClickListener) { - this.context = context; - this.itemClickListener = itemClickListener; - } - - @NonNull - @Override - public FlairViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new FlairViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_flair, null, false)); - } - - @Override - public void onBindViewHolder(@NonNull FlairViewHolder holder, int position) { - if(flairs.get(holder.getAdapterPosition()).isEditable()) { - holder.editFlairImageView.setVisibility(View.VISIBLE); - holder.editFlairImageView.setOnClickListener(view -> { - View dialogView = ((Activity) context).getLayoutInflater().inflate(R.layout.dialog_edit_flair, null); - EditText flairEditText = dialogView.findViewById(R.id.flair_edit_text_edit_flair_dialog); - flairEditText.requestFocus(); - InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); - if(imm != null) { - imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); - } - new MaterialAlertDialogBuilder(context, R.style.MaterialAlertDialogTheme) - .setTitle(R.string.edit_flair) - .setView(dialogView) - .setPositiveButton(R.string.ok, (dialogInterface, i) - -> { - Flair flair = flairs.get(holder.getAdapterPosition()); - flair.setText(flairEditText.getText().toString()); - itemClickListener.onClick(flair); - }) - .setNegativeButton(R.string.cancel, null) - .show(); - }); - } - - if(flairs.get(holder.getAdapterPosition()).isEditable() && flairs.get(holder.getAdapterPosition()).getText().equals("")) { - holder.itemView.setOnClickListener(view -> holder.editFlairImageView.performClick()); - } else { - holder.itemView.setOnClickListener(view -> itemClickListener.onClick(flairs.get(holder.getAdapterPosition()))); - } - - holder.flairTextView.setText(flairs.get(holder.getAdapterPosition()).getText()); - } - - @Override - public int getItemCount() { - return flairs == null ? 0 : flairs.size(); - } - - @Override - public void onViewRecycled(@NonNull FlairViewHolder holder) { - super.onViewRecycled(holder); - holder.editFlairImageView.setVisibility(View.GONE); - } - - void changeDataset(ArrayList flairs) { - this.flairs = flairs; - notifyDataSetChanged(); - } - - class FlairViewHolder extends RecyclerView.ViewHolder { - View itemView; - @BindView(R.id.flair_text_view_item_flair) TextView flairTextView; - @BindView(R.id.edit_flair_image_view_item_flair) ImageView editFlairImageView; - - FlairViewHolder(@NonNull View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - this.itemView = itemView; - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FollowedUsersListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FollowedUsersListingFragment.java deleted file mode 100644 index cabbe6ed..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FollowedUsersListingFragment.java +++ /dev/null @@ -1,100 +0,0 @@ -package ml.docilealligator.infinityforreddit; - - -import android.app.Activity; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.LinearLayout; - -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProvider; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; - -import javax.inject.Inject; - -import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserViewModel; -import butterknife.BindView; -import butterknife.ButterKnife; - - -/** - * A simple {@link Fragment} subclass. - */ -public class FollowedUsersListingFragment extends Fragment { - - static final String EXTRA_ACCOUNT_NAME = "EAN"; - - @BindView(R.id.recycler_view_followed_users_listing_fragment) RecyclerView mRecyclerView; - @BindView(R.id.no_subscriptions_linear_layout_followed_users_listing_fragment) LinearLayout mLinearLayout; - @BindView(R.id.no_subscriptions_image_view_followed_users_listing_fragment) ImageView mImageView; - - private Activity mActivity; - - private RequestManager mGlide; - - private SubscribedUserViewModel mSubscribedUserViewModel; - - public FollowedUsersListingFragment() { - // Required empty public constructor - } - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_followed_users_listing, container, false); - - ButterKnife.bind(this, rootView); - - mActivity = getActivity(); - - ((Infinity) mActivity.getApplication()).getAppComponent().inject(this); - - Resources resources = getResources(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { - int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); - if (navBarResourceId > 0) { - mRecyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); - } - } - } - - mGlide = Glide.with(this); - - mRecyclerView.setLayoutManager(new LinearLayoutManager(mActivity)); - FollowedUsersRecyclerViewAdapter adapter = new FollowedUsersRecyclerViewAdapter(mActivity); - mRecyclerView.setAdapter(adapter); - - mSubscribedUserViewModel = new ViewModelProvider(this, - new SubscribedUserViewModel.Factory(mActivity.getApplication(), mRedditDataRoomDatabase, getArguments().getString(EXTRA_ACCOUNT_NAME))) - .get(SubscribedUserViewModel.class); - mSubscribedUserViewModel.getAllSubscribedUsers().observe(this, subscribedUserData -> { - if (subscribedUserData == null || subscribedUserData.size() == 0) { - mRecyclerView.setVisibility(View.GONE); - mLinearLayout.setVisibility(View.VISIBLE); - mGlide.load(R.drawable.error_image).into(mImageView); - } else { - mLinearLayout.setVisibility(View.GONE); - mRecyclerView.setVisibility(View.VISIBLE); - } - adapter.setSubscribedUsers(subscribedUserData); - }); - - return rootView; - } - -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FollowedUsersRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FollowedUsersRecyclerViewAdapter.java deleted file mode 100644 index 44d02068..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FollowedUsersRecyclerViewAdapter.java +++ /dev/null @@ -1,89 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Context; -import android.content.Intent; -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 com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.bumptech.glide.request.RequestOptions; - -import java.util.List; - -import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserData; -import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import pl.droidsonroids.gif.GifImageView; - -public class FollowedUsersRecyclerViewAdapter extends RecyclerView.Adapter { - private List mSubscribedUserData; - private Context mContext; - private RequestManager glide; - - FollowedUsersRecyclerViewAdapter(Context context) { - mContext = context; - glide = Glide.with(context.getApplicationContext()); - } - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { - return new UserViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_subscribed_thing, viewGroup, false)); - } - - @Override - public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, int i) { - viewHolder.itemView.setOnClickListener(view -> { - Intent intent = new Intent(mContext, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mSubscribedUserData.get(viewHolder.getAdapterPosition()).getName()); - mContext.startActivity(intent); - }); - if(!mSubscribedUserData.get(i).getIconUrl().equals("")) { - glide.load(mSubscribedUserData.get(i).getIconUrl()) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(glide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(((UserViewHolder) viewHolder).iconGifImageView); - } else { - glide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(((UserViewHolder) viewHolder).iconGifImageView); - } - ((UserViewHolder) viewHolder).subredditNameTextView.setText(mSubscribedUserData.get(i).getName()); - } - - @Override - public int getItemCount() { - if(mSubscribedUserData != null) { - return mSubscribedUserData.size(); - } - return 0; - } - - @Override - public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { - glide.clear(((UserViewHolder) holder).iconGifImageView); - } - - void setSubscribedUsers(List subscribedUsers){ - mSubscribedUserData = subscribedUsers; - notifyDataSetChanged(); - } - - - private class UserViewHolder extends RecyclerView.ViewHolder { - private final GifImageView iconGifImageView; - private final TextView subredditNameTextView; - - public UserViewHolder(View itemView) { - super(itemView); - iconGifImageView = itemView.findViewById(R.id.subreddit_icon_gif_image_view_item_subscribed_subreddit); - subredditNameTextView = itemView.findViewById(R.id.subreddit_name_text_view_item_subscribed_subreddit); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/CommentsListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/CommentsListingFragment.java new file mode 100644 index 00000000..6b4da7ff --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/CommentsListingFragment.java @@ -0,0 +1,225 @@ +package ml.docilealligator.infinityforreddit.Fragment; + + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.Adapter.CommentsListingRecyclerViewAdapter; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.CommentViewModel; +import ml.docilealligator.infinityforreddit.FragmentCommunicator; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.NetworkState; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import retrofit2.Retrofit; + + +/** + * A simple {@link Fragment} subclass. + */ +public class CommentsListingFragment extends Fragment implements FragmentCommunicator { + + public static final String EXTRA_USERNAME = "EN"; + public static final String EXTRA_ACCESS_TOKEN = "EAT"; + public static final String EXTRA_ACCOUNT_NAME = "EAN"; + public static final String EXTRA_ARE_SAVED_COMMENTS = "EISC"; + + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + + @BindView(R.id.coordinator_layout_comments_listing_fragment) CoordinatorLayout mCoordinatorLayout; + @BindView(R.id.recycler_view_comments_listing_fragment) RecyclerView mCommentRecyclerView; + @BindView(R.id.progress_bar_comments_listing_fragment) CircleProgressBar mProgressBar; + @BindView(R.id.fetch_comments_info_linear_layout_comments_listing_fragment) LinearLayout mFetchCommentInfoLinearLayout; + @BindView(R.id.fetch_comments_info_image_view_comments_listing_fragment) ImageView mFetchCommentInfoImageView; + @BindView(R.id.fetch_comments_info_text_view_comments_listing_fragment) TextView mFetchCommentInfoTextView; + + private boolean mNullAccessToken = false; + private String mAccessToken; + + private RequestManager mGlide; + + private Activity activity; + + private CommentsListingRecyclerViewAdapter mAdapter; + + CommentViewModel mCommentViewModel; + + @Inject + @Named("no_oauth") + Retrofit mRetrofit; + + @Inject @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + public CommentsListingFragment() { + // Required empty public constructor + } + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_comments_listing, container, false); + + ((Infinity) activity.getApplication()).getAppComponent().inject(this); + + ButterKnife.bind(this, rootView); + + mGlide = Glide.with(activity); + + Resources resources = getResources(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { + int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); + if (navBarResourceId > 0) { + mCommentRecyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); + } + } + } + + if (savedInstanceState == null) { + getCurrentAccountAndBindView(resources); + } else { + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + + if (!mNullAccessToken && mAccessToken == null) { + getCurrentAccountAndBindView(resources); + } else { + bindView(resources); + } + } + + return rootView; + } + + private void getCurrentAccountAndBindView(Resources resources) { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + } + bindView(resources); + }).execute(); + } + + private void bindView(Resources resources) { + mCommentRecyclerView.setLayoutManager(new LinearLayoutManager(activity)); + + mAdapter = new CommentsListingRecyclerViewAdapter(activity, mOauthRetrofit, + getArguments().getString(EXTRA_ACCESS_TOKEN), getArguments().getString(EXTRA_ACCOUNT_NAME), + () -> mCommentViewModel.retryLoadingMore()); + + String username = getArguments().getString(EXTRA_USERNAME); + + mCommentRecyclerView.setAdapter(mAdapter); + + CommentViewModel.Factory factory; + + if(mAccessToken == null) { + factory = new CommentViewModel.Factory(mRetrofit, + resources.getConfiguration().locale, mAccessToken, username, PostDataSource.SORT_TYPE_NEW, + getArguments().getBoolean(EXTRA_ARE_SAVED_COMMENTS)); + } else { + factory = new CommentViewModel.Factory(mOauthRetrofit, + resources.getConfiguration().locale, mAccessToken, username, PostDataSource.SORT_TYPE_NEW, + getArguments().getBoolean(EXTRA_ARE_SAVED_COMMENTS)); + } + + mCommentViewModel = new ViewModelProvider(this, factory).get(CommentViewModel.class); + mCommentViewModel.getComments().observe(this, comments -> mAdapter.submitList(comments)); + + mCommentViewModel.hasComment().observe(this, hasComment -> { + mProgressBar.setVisibility(View.GONE); + if(hasComment) { + mFetchCommentInfoLinearLayout.setVisibility(View.GONE); + } else { + mFetchCommentInfoLinearLayout.setOnClickListener(view -> { + //Do nothing + }); + showErrorView(R.string.no_comments); + } + }); + + mCommentViewModel.getInitialLoadingState().observe(this, networkState -> { + if(networkState.getStatus().equals(NetworkState.Status.SUCCESS)) { + mProgressBar.setVisibility(View.GONE); + } else if(networkState.getStatus().equals(NetworkState.Status.FAILED)) { + mProgressBar.setVisibility(View.GONE); + mFetchCommentInfoLinearLayout.setOnClickListener(view -> refresh()); + showErrorView(R.string.load_comments_failed); + } else { + mProgressBar.setVisibility(View.VISIBLE); + } + }); + + mCommentViewModel.getPaginationNetworkState().observe(this, networkState -> mAdapter.setNetworkState(networkState)); + } + + public void changeSortType(String sortType) { + mCommentViewModel.changeSortType(sortType); + } + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + this.activity = (Activity) context; + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + } + + @Override + public void refresh() { + mFetchCommentInfoLinearLayout.setVisibility(View.GONE); + mCommentViewModel.refresh(); + mAdapter.setNetworkState(null); + } + + private void showErrorView(int stringResId) { + if(activity != null && isAdded()) { + mProgressBar.setVisibility(View.GONE); + mFetchCommentInfoLinearLayout.setVisibility(View.VISIBLE); + mFetchCommentInfoTextView.setText(stringResId); + mGlide.load(R.drawable.error_image).into(mFetchCommentInfoImageView); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/FlairBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/FlairBottomSheetFragment.java new file mode 100644 index 00000000..0435cef7 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/FlairBottomSheetFragment.java @@ -0,0 +1,125 @@ +package ml.docilealligator.infinityforreddit.Fragment; + + +import android.app.Activity; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ProgressBar; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; + +import java.util.ArrayList; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.Adapter.FlairBottomSheetRecyclerViewAdapter; +import ml.docilealligator.infinityforreddit.FetchFlairs; +import ml.docilealligator.infinityforreddit.Flair; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import retrofit2.Retrofit; + + +/** + * A simple {@link Fragment} subclass. + */ +public class FlairBottomSheetFragment extends BottomSheetDialogFragment { + + public interface FlairSelectionCallback { + void flairSelected(Flair flair); + } + + public static final String EXTRA_ACCESS_TOKEN = "EAT"; + public static final String EXTRA_SUBREDDIT_NAME = "ESN"; + + @BindView(R.id.progress_bar_flair_bottom_sheet_fragment) ProgressBar progressBar; + @BindView(R.id.error_text_view_flair_bottom_sheet_fragment) TextView errorTextView; + @BindView(R.id.recycler_view_bottom_sheet_fragment) RecyclerView recyclerView; + + private String mAccessToken; + private String mSubredditName; + + private Activity mActivity; + private FlairBottomSheetRecyclerViewAdapter mAdapter; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + @Named("no_oauth") + Retrofit mRetrofit; + + public FlairBottomSheetFragment() { + // Required empty public constructor + } + + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_flair_bottom_sheet, container, false); + + ButterKnife.bind(this, rootView); + + mActivity = getActivity(); + + ((Infinity) mActivity.getApplication()).getAppComponent().inject(this); + + /*if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O + && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + }*/ + + mAdapter = new FlairBottomSheetRecyclerViewAdapter(mActivity, flair -> { + ((FlairSelectionCallback) mActivity).flairSelected(flair); + dismiss(); + }); + + recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + recyclerView.setAdapter(mAdapter); + + mAccessToken = getArguments().getString(EXTRA_ACCESS_TOKEN); + mSubredditName = getArguments().getString(EXTRA_SUBREDDIT_NAME); + + fetchFlairs(); + + return rootView; + } + + private void fetchFlairs() { + FetchFlairs.fetchFlairsInSubreddit(mOauthRetrofit, mAccessToken, + mSubredditName, new FetchFlairs.FetchFlairsInSubredditListener() { + @Override + public void fetchSuccessful(ArrayList flairs) { + progressBar.setVisibility(View.GONE); + if(flairs == null || flairs.size() == 0) { + errorTextView.setVisibility(View.VISIBLE); + errorTextView.setText(R.string.no_flair); + } else { + errorTextView.setVisibility(View.GONE); + mAdapter.changeDataset(flairs); + } + } + + @Override + public void fetchFailed() { + progressBar.setVisibility(View.GONE); + errorTextView.setVisibility(View.VISIBLE); + errorTextView.setText(R.string.error_loading_flairs); + errorTextView.setOnClickListener(view -> fetchFlairs()); + } + }); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/FollowedUsersListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/FollowedUsersListingFragment.java new file mode 100644 index 00000000..3de48bb8 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/FollowedUsersListingFragment.java @@ -0,0 +1,104 @@ +package ml.docilealligator.infinityforreddit.Fragment; + + +import android.app.Activity; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; + +import javax.inject.Inject; + +import ml.docilealligator.infinityforreddit.Adapter.FollowedUsersRecyclerViewAdapter; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserViewModel; +import butterknife.BindView; +import butterknife.ButterKnife; + + +/** + * A simple {@link Fragment} subclass. + */ +public class FollowedUsersListingFragment extends Fragment { + + public static final String EXTRA_ACCOUNT_NAME = "EAN"; + + @BindView(R.id.recycler_view_followed_users_listing_fragment) RecyclerView mRecyclerView; + @BindView(R.id.no_subscriptions_linear_layout_followed_users_listing_fragment) LinearLayout mLinearLayout; + @BindView(R.id.no_subscriptions_image_view_followed_users_listing_fragment) ImageView mImageView; + + private Activity mActivity; + + private RequestManager mGlide; + + private SubscribedUserViewModel mSubscribedUserViewModel; + + public FollowedUsersListingFragment() { + // Required empty public constructor + } + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_followed_users_listing, container, false); + + ButterKnife.bind(this, rootView); + + mActivity = getActivity(); + + ((Infinity) mActivity.getApplication()).getAppComponent().inject(this); + + Resources resources = getResources(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { + int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); + if (navBarResourceId > 0) { + mRecyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); + } + } + } + + mGlide = Glide.with(this); + + mRecyclerView.setLayoutManager(new LinearLayoutManager(mActivity)); + FollowedUsersRecyclerViewAdapter adapter = new FollowedUsersRecyclerViewAdapter(mActivity); + mRecyclerView.setAdapter(adapter); + + mSubscribedUserViewModel = new ViewModelProvider(this, + new SubscribedUserViewModel.Factory(mActivity.getApplication(), mRedditDataRoomDatabase, getArguments().getString(EXTRA_ACCOUNT_NAME))) + .get(SubscribedUserViewModel.class); + mSubscribedUserViewModel.getAllSubscribedUsers().observe(this, subscribedUserData -> { + if (subscribedUserData == null || subscribedUserData.size() == 0) { + mRecyclerView.setVisibility(View.GONE); + mLinearLayout.setVisibility(View.VISIBLE); + mGlide.load(R.drawable.error_image).into(mImageView); + } else { + mLinearLayout.setVisibility(View.GONE); + mRecyclerView.setVisibility(View.VISIBLE); + } + adapter.setSubscribedUsers(subscribedUserData); + }); + + return rootView; + } + +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/ModifyCommentBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/ModifyCommentBottomSheetFragment.java new file mode 100644 index 00000000..cf3d99f0 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/ModifyCommentBottomSheetFragment.java @@ -0,0 +1,88 @@ +package ml.docilealligator.infinityforreddit.Fragment; + + +import android.app.Activity; +import android.content.Intent; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.fragment.app.Fragment; + +import com.deishelon.roundedbottomsheet.RoundedBottomSheetDialogFragment; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.Activity.EditCommentActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewPostDetailActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewUserDetailActivity; +import ml.docilealligator.infinityforreddit.R; + + +/** + * A simple {@link Fragment} subclass. + */ +public class ModifyCommentBottomSheetFragment extends RoundedBottomSheetDialogFragment { + + public static final String EXTRA_COMMENT_FULLNAME = "ECF"; + public static final String EXTRA_COMMENT_CONTENT = "ECC"; + public static final String EXTRA_ACCESS_TOKEN = "EAT"; + public static final String EXTRA_POSITION = "EP"; + + public ModifyCommentBottomSheetFragment() { + // Required empty public constructor + } + + @BindView(R.id.edit_text_view_modify_comment_bottom_sheet_fragment) TextView editTextView; + @BindView(R.id.delete_text_view_modify_comment_bottom_sheet_fragment) TextView deleteTextView; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_modify_comment_bottom_sheet, container, false); + ButterKnife.bind(this, rootView); + + Activity activity = getActivity(); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O + && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + + Bundle bundle = getArguments(); + String fullName = bundle.getString(EXTRA_COMMENT_FULLNAME); + String content = bundle.getString(EXTRA_COMMENT_CONTENT); + String accessToken = bundle.getString(EXTRA_ACCESS_TOKEN); + + editTextView.setOnClickListener(view -> { + Intent intent = new Intent(activity, EditCommentActivity.class); + intent.putExtra(EditCommentActivity.EXTRA_ACCESS_TOKEN, accessToken); + intent.putExtra(EditCommentActivity.EXTRA_FULLNAME, fullName); + intent.putExtra(EditCommentActivity.EXTRA_CONTENT, content); + intent.putExtra(EditCommentActivity.EXTRA_POSITION, bundle.getInt(EXTRA_POSITION)); + if(activity instanceof ViewPostDetailActivity) { + activity.startActivityForResult(intent, ViewPostDetailActivity.EDIT_COMMENT_REQUEST_CODE); + } else { + startActivity(intent); + } + + dismiss(); + }); + + deleteTextView.setOnClickListener(view -> { + dismiss(); + if(activity instanceof ViewPostDetailActivity) { + ((ViewPostDetailActivity) activity).deleteComment(fullName, bundle.getInt(EXTRA_POSITION)); + } else if(activity instanceof ViewUserDetailActivity) { + ((ViewUserDetailActivity) activity).deleteComment(fullName); + } + }); + + return rootView; + } + +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java new file mode 100644 index 00000000..21e130bd --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java @@ -0,0 +1,683 @@ +package ml.docilealligator.infinityforreddit.Fragment; + + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.graphics.Rect; +import android.os.Build; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.os.Handler; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.DimenRes; +import androidx.annotation.NonNull; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; +import androidx.paging.PagedList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.LinearSmoothScroller; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.Activity.FilteredThingActivity; +import ml.docilealligator.infinityforreddit.Activity.MainActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewSubredditDetailActivity; +import ml.docilealligator.infinityforreddit.Adapter.PostRecyclerViewAdapter; +import ml.docilealligator.infinityforreddit.Event.ChangeNSFWBlurEvent; +import ml.docilealligator.infinityforreddit.Event.ChangeSpoilerBlurEvent; +import ml.docilealligator.infinityforreddit.Event.PostUpdateEventToPostList; +import ml.docilealligator.infinityforreddit.FragmentCommunicator; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.NetworkState; +import ml.docilealligator.infinityforreddit.Post; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.PostViewModel; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; +import retrofit2.Retrofit; + + +/** + * A simple {@link Fragment} subclass. + */ +public class PostFragment extends Fragment implements FragmentCommunicator { + + public static final String EXTRA_NAME = "EN"; + public static final String EXTRA_USER_NAME = "EUN"; + public static final String EXTRA_USER_WHERE = "EUW"; + public static final String EXTRA_QUERY = "EQ"; + public static final String EXTRA_POST_TYPE = "EPT"; + public static final String EXTRA_SORT_TYPE = "EST"; + public static final String EXTRA_FILTER = "EF"; + public static final int EXTRA_NO_FILTER = -2; + public static final String EXTRA_ACCESS_TOKEN = "EAT"; + + private static final String IS_IN_LAZY_MODE_STATE = "IILMS"; + private static final String RECYCLER_VIEW_POSITION_STATE = "RVPS"; + + @BindView(R.id.recycler_view_post_fragment) RecyclerView mPostRecyclerView; + @BindView(R.id.progress_bar_post_fragment) CircleProgressBar mProgressBar; + @BindView(R.id.fetch_post_info_linear_layout_post_fragment) LinearLayout mFetchPostInfoLinearLayout; + @BindView(R.id.fetch_post_info_image_view_post_fragment) ImageView mFetchPostInfoImageView; + @BindView(R.id.fetch_post_info_text_view_post_fragment) TextView mFetchPostInfoTextView; + + private RequestManager mGlide; + + private Activity activity; + private LinearLayoutManager mLinearLayoutManager; + private StaggeredGridLayoutManager mStaggeredGridLayoutManager; + + private boolean isInLazyMode = false; + private boolean isLazyModePaused = false; + private boolean hasPost = false; + + private PostRecyclerViewAdapter mAdapter; + private RecyclerView.SmoothScroller smoothScroller; + + PostViewModel mPostViewModel; + + private Window window; + private Handler lazyModeHandler; + private LazyModeRunnable lazyModeRunnable; + private CountDownTimer resumeLazyModeCountDownTimer; + + private float lazyModeInterval; + + @Inject @Named("no_oauth") + Retrofit mRetrofit; + + @Inject @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + public PostFragment() { + // Required empty public constructor + } + + @Override + public void onResume() { + super.onResume(); + if(mPostRecyclerView.getAdapter() != null) { + ((PostRecyclerViewAdapter) mPostRecyclerView.getAdapter()).setCanStartActivity(true); + } + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View rootView = inflater.inflate(R.layout.fragment_post, container, false); + + ((Infinity) activity.getApplication()).getAppComponent().inject(this); + + ButterKnife.bind(this, rootView); + + EventBus.getDefault().register(this); + + lazyModeHandler = new Handler(); + + lazyModeInterval = Float.parseFloat(mSharedPreferences.getString(SharedPreferencesUtils.LAZY_MODE_INTERVAL_KEY, "2.5")); + + smoothScroller = new LinearSmoothScroller(activity) { + @Override + protected int getVerticalSnapPreference() { + return LinearSmoothScroller.SNAP_TO_START; + } + }; + + window = activity.getWindow(); + + Resources resources = getResources(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { + int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); + if (navBarResourceId > 0) { + mPostRecyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); + } + } + } + + if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT && !resources.getBoolean(R.bool.isTablet)) { + mLinearLayoutManager = new LinearLayoutManager(activity); + mPostRecyclerView.setLayoutManager(mLinearLayoutManager); + } else { + mStaggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); + mPostRecyclerView.setLayoutManager(mStaggeredGridLayoutManager); + StaggeredGridLayoutManagerItemOffsetDecoration itemDecoration = + new StaggeredGridLayoutManagerItemOffsetDecoration(activity, R.dimen.staggeredLayoutManagerItemOffset); + mPostRecyclerView.addItemDecoration(itemDecoration); + } + + mGlide = Glide.with(activity); + + lazyModeRunnable = new LazyModeRunnable() { + + @Override + public void run() { + if(isInLazyMode && !isLazyModePaused) { + int nPosts = mAdapter.getItemCount(); + if(getCurrentPosition() == -1) { + if(mLinearLayoutManager != null) { + setCurrentPosition(mLinearLayoutManager.findFirstVisibleItemPosition()); + } else { + int[] into = new int[2]; + setCurrentPosition(mStaggeredGridLayoutManager.findFirstVisibleItemPositions(into)[1]); + } + } + + if(getCurrentPosition() != RecyclerView.NO_POSITION && nPosts > getCurrentPosition()) { + incrementCurrentPosition(); + smoothScroller.setTargetPosition(getCurrentPosition()); + if(mLinearLayoutManager != null) { + mLinearLayoutManager.startSmoothScroll(smoothScroller); + } else { + mStaggeredGridLayoutManager.startSmoothScroll(smoothScroller); + } + } + } + lazyModeHandler.postDelayed(this, (long) (lazyModeInterval * 1000)); + } + }; + + resumeLazyModeCountDownTimer = new CountDownTimer((long) (lazyModeInterval * 1000), (long) (lazyModeInterval * 1000)) { + @Override + public void onTick(long l) { + + } + + @Override + public void onFinish() { + resumeLazyMode(true); + } + }; + + if(savedInstanceState != null) { + int recyclerViewPosition = savedInstanceState.getInt(RECYCLER_VIEW_POSITION_STATE); + if(recyclerViewPosition > 0) { + mPostRecyclerView.scrollToPosition(recyclerViewPosition); + } + + isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); + if(isInLazyMode) { + resumeLazyMode(false); + } + } + + mPostRecyclerView.setOnTouchListener((view, motionEvent) -> { + if(isInLazyMode) { + pauseLazyMode(true); + } + return false; + }); + + if(activity instanceof MainActivity) { + mPostRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + if (dy > 0) { + ((MainActivity) activity).postScrollDown(); + } else if (dy < 0) { + ((MainActivity) activity).postScrollUp(); + } + + } + }); + } else if(activity instanceof ViewSubredditDetailActivity) { + mPostRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + if (dy > 0) { + ((ViewSubredditDetailActivity) activity).postScrollDown(); + } else if (dy < 0) { + ((ViewSubredditDetailActivity) activity).postScrollUp(); + } + + } + }); + } + + int postType = getArguments().getInt(EXTRA_POST_TYPE); + String sortType = getArguments().getString(EXTRA_SORT_TYPE); + + int filter = getArguments().getInt(EXTRA_FILTER); + String accessToken = getArguments().getString(EXTRA_ACCESS_TOKEN); + boolean nsfw = mSharedPreferences.getBoolean(SharedPreferencesUtils.NSFW_KEY, false); + boolean needBlurNsfw = mSharedPreferences.getBoolean(SharedPreferencesUtils.BLUR_NSFW_KEY, true); + boolean needBlurSpoiler = mSharedPreferences.getBoolean(SharedPreferencesUtils.BLUR_SPOILER_KEY, false); + + PostViewModel.Factory factory; + + if(postType == PostDataSource.TYPE_SEARCH) { + String subredditName = getArguments().getString(EXTRA_NAME); + String query = getArguments().getString(EXTRA_QUERY); + + mAdapter = new PostRecyclerViewAdapter(activity, mOauthRetrofit, mRetrofit, mRedditDataRoomDatabase, + accessToken, postType, true, needBlurNsfw, needBlurSpoiler, + new PostRecyclerViewAdapter.Callback() { + @Override + public void retryLoadingMore() { + mPostViewModel.retryLoadingMore(); + } + + @Override + public void typeChipClicked(int filter) { + Intent intent = new Intent(activity, FilteredThingActivity.class); + intent.putExtra(FilteredThingActivity.EXTRA_NAME, subredditName); + intent.putExtra(FilteredThingActivity.EXTRA_QUERY, query); + intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, postType); + intent.putExtra(FilteredThingActivity.EXTRA_SORT_TYPE, sortType); + intent.putExtra(FilteredThingActivity.EXTRA_FILTER, filter); + startActivity(intent); + } + }); + + if(accessToken == null) { + factory = new PostViewModel.Factory(mRetrofit, accessToken, + getResources().getConfiguration().locale, subredditName, query, postType, + sortType, filter, nsfw); + } else { + factory = new PostViewModel.Factory(mOauthRetrofit, accessToken, + getResources().getConfiguration().locale, subredditName, query, postType, + sortType, filter, nsfw); + } + } else if(postType == PostDataSource.TYPE_SUBREDDIT) { + String subredditName = getArguments().getString(EXTRA_NAME); + + boolean displaySubredditName = subredditName != null && (subredditName.equals("popular") || subredditName.equals("all")); + mAdapter = new PostRecyclerViewAdapter(activity, mOauthRetrofit, mRetrofit, mRedditDataRoomDatabase, + accessToken, postType, displaySubredditName, needBlurNsfw, needBlurSpoiler, + new PostRecyclerViewAdapter.Callback() { + @Override + public void retryLoadingMore() { + mPostViewModel.retryLoadingMore(); + } + + @Override + public void typeChipClicked(int filter) { + Intent intent = new Intent(activity, FilteredThingActivity.class); + intent.putExtra(FilteredThingActivity.EXTRA_NAME, subredditName); + intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, postType); + intent.putExtra(FilteredThingActivity.EXTRA_SORT_TYPE, sortType); + intent.putExtra(FilteredThingActivity.EXTRA_FILTER, filter); + startActivity(intent); + } + }); + + if(accessToken == null) { + factory = new PostViewModel.Factory(mRetrofit, accessToken, + getResources().getConfiguration().locale, subredditName, postType, sortType, + filter, nsfw); + } else { + factory = new PostViewModel.Factory(mOauthRetrofit, accessToken, + getResources().getConfiguration().locale, subredditName, postType, sortType, + filter, nsfw); + } + } else if(postType == PostDataSource.TYPE_USER) { + String username = getArguments().getString(EXTRA_USER_NAME); + String where = getArguments().getString(EXTRA_USER_WHERE); + if(where != null && where.equals(PostDataSource.USER_WHERE_SUBMITTED)) { + CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) mFetchPostInfoLinearLayout.getLayoutParams(); + params.height = ViewGroup.LayoutParams.WRAP_CONTENT; + mFetchPostInfoLinearLayout.setLayoutParams(params); + } + + mAdapter = new PostRecyclerViewAdapter(activity, mOauthRetrofit, mRetrofit, mRedditDataRoomDatabase, + accessToken, postType, true, needBlurNsfw, needBlurSpoiler, + new PostRecyclerViewAdapter.Callback() { + @Override + public void retryLoadingMore() { + mPostViewModel.retryLoadingMore(); + } + + @Override + public void typeChipClicked(int filter) { + Intent intent = new Intent(activity, FilteredThingActivity.class); + intent.putExtra(FilteredThingActivity.EXTRA_NAME, username); + intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, postType); + intent.putExtra(FilteredThingActivity.EXTRA_SORT_TYPE, sortType); + intent.putExtra(FilteredThingActivity.EXTRA_USER_WHERE, where); + intent.putExtra(FilteredThingActivity.EXTRA_FILTER, filter); + startActivity(intent); + } + }); + + if(accessToken == null) { + factory = new PostViewModel.Factory(mRetrofit, accessToken, + getResources().getConfiguration().locale, username, postType, sortType, where, + filter, nsfw); + } else { + factory = new PostViewModel.Factory(mOauthRetrofit, accessToken, + getResources().getConfiguration().locale, username, postType, sortType, where, + filter, nsfw); + } + } else { + mAdapter = new PostRecyclerViewAdapter(activity, mOauthRetrofit, mRetrofit, mRedditDataRoomDatabase, + accessToken, postType, true, needBlurNsfw, needBlurSpoiler, + new PostRecyclerViewAdapter.Callback() { + @Override + public void retryLoadingMore() { + mPostViewModel.retryLoadingMore(); + } + + @Override + public void typeChipClicked(int filter) { + Intent intent = new Intent(activity, FilteredThingActivity.class); + intent.putExtra(FilteredThingActivity.EXTRA_NAME, activity.getString(R.string.best)); + intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, postType); + intent.putExtra(FilteredThingActivity.EXTRA_SORT_TYPE, sortType); + intent.putExtra(FilteredThingActivity.EXTRA_FILTER, filter); + startActivity(intent); + } + }); + + factory = new PostViewModel.Factory(mOauthRetrofit, accessToken, + getResources().getConfiguration().locale, postType, sortType, filter, nsfw); + } + + mPostRecyclerView.setAdapter(mAdapter); + + mPostViewModel = new ViewModelProvider(this, factory).get(PostViewModel.class); + mPostViewModel.getPosts().observe(this, posts -> mAdapter.submitList(posts)); + + mPostViewModel.hasPost().observe(this, hasPost -> { + this.hasPost = hasPost; + mProgressBar.setVisibility(View.GONE); + if(hasPost) { + mFetchPostInfoLinearLayout.setVisibility(View.GONE); + } else { + if(isInLazyMode) { + stopLazyMode(); + } + + mFetchPostInfoLinearLayout.setOnClickListener(view -> {}); + showErrorView(R.string.no_posts); + } + }); + + mPostViewModel.getInitialLoadingState().observe(this, networkState -> { + if(networkState.getStatus().equals(NetworkState.Status.SUCCESS)) { + mProgressBar.setVisibility(View.GONE); + } else if(networkState.getStatus().equals(NetworkState.Status.FAILED)) { + mProgressBar.setVisibility(View.GONE); + mFetchPostInfoLinearLayout.setOnClickListener(view -> refresh()); + showErrorView(R.string.load_posts_error); + } else { + mProgressBar.setVisibility(View.VISIBLE); + } + }); + + mPostViewModel.getPaginationNetworkState().observe(this, networkState -> mAdapter.setNetworkState(networkState)); + + return rootView; + } + + public void changeSortType(String sortType) { + mPostViewModel.changeSortType(sortType); + } + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + this.activity = (Activity) context; + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(IS_IN_LAZY_MODE_STATE, isInLazyMode); + if(mLinearLayoutManager != null) { + outState.putInt(RECYCLER_VIEW_POSITION_STATE, mLinearLayoutManager.findFirstVisibleItemPosition()); + } else if(mStaggeredGridLayoutManager != null) { + int[] into = new int[2]; + outState.putInt(RECYCLER_VIEW_POSITION_STATE, + mStaggeredGridLayoutManager.findFirstVisibleItemPositions(into)[0]); + } + } + + @Override + public void refresh() { + if(isInLazyMode) { + stopLazyMode(); + } + + mAdapter.setNetworkState(null); + mFetchPostInfoLinearLayout.setVisibility(View.GONE); + hasPost = false; + mPostViewModel.refresh(); + } + + private void showErrorView(int stringResId) { + if(activity != null && isAdded()) { + mProgressBar.setVisibility(View.GONE); + mFetchPostInfoLinearLayout.setVisibility(View.VISIBLE); + mFetchPostInfoTextView.setText(stringResId); + mGlide.load(R.drawable.error_image).into(mFetchPostInfoImageView); + } + } + + @Override + public void changeNSFW(boolean nsfw) { + mPostViewModel.changeNSFW(nsfw); + } + + @Override + public boolean startLazyMode() { + if(!hasPost) { + Toast.makeText(activity, R.string.no_posts_no_lazy_mode, Toast.LENGTH_SHORT).show(); + return false; + } + + isInLazyMode = true; + isLazyModePaused = false; + + lazyModeInterval = Float.parseFloat(mSharedPreferences.getString(SharedPreferencesUtils.LAZY_MODE_INTERVAL_KEY, "2.5")); + lazyModeHandler.postDelayed(lazyModeRunnable, (long) (lazyModeInterval * 1000)); + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + Toast.makeText(activity, getString(R.string.lazy_mode_start, lazyModeInterval), + Toast.LENGTH_SHORT).show(); + + return true; + } + + @Override + public void stopLazyMode() { + isInLazyMode = false; + isLazyModePaused = false; + lazyModeRunnable.resetOldPosition(); + lazyModeHandler.removeCallbacks(lazyModeRunnable); + resumeLazyModeCountDownTimer.cancel(); + window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + Toast.makeText(activity, getString(R.string.lazy_mode_stop), Toast.LENGTH_SHORT).show(); + } + + @Override + public void resumeLazyMode(boolean resumeNow) { + if(isInLazyMode) { + isLazyModePaused = false; + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + lazyModeRunnable.resetOldPosition(); + + if(resumeNow) { + lazyModeHandler.post(lazyModeRunnable); + } else { + lazyModeHandler.postDelayed(lazyModeRunnable, (long) (lazyModeInterval * 1000)); + } + } + } + + @Override + public void pauseLazyMode(boolean startTimer) { + resumeLazyModeCountDownTimer.cancel(); + isInLazyMode = true; + isLazyModePaused = true; + lazyModeHandler.removeCallbacks(lazyModeRunnable); + window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + if(startTimer) { + resumeLazyModeCountDownTimer.start(); + } + } + + @Override + public boolean isInLazyMode() { + return isInLazyMode; + } + + @Subscribe + public void onPostUpdateEvent(PostUpdateEventToPostList event) { + PagedList posts = mAdapter.getCurrentList(); + if (posts != null && event.positionInList >= 0 && event.positionInList < posts.size()) { + Post post = posts.get(event.positionInList); + if (post != null && post.getFullName().equals(event.post.getFullName())) { + post.setTitle(event.post.getTitle()); + post.setVoteType(event.post.getVoteType()); + post.setScore(event.post.getScore()); + post.setNSFW(event.post.isNSFW()); + post.setHidden(event.post.isHidden()); + post.setSpoiler(event.post.isSpoiler()); + post.setFlair(event.post.getFlair()); + post.setSaved(event.post.isSaved()); + mAdapter.notifyItemChanged(event.positionInList); + } + } + } + + @Subscribe + public void onChangeNSFWBlurEvent(ChangeNSFWBlurEvent event) { + mAdapter.setBlurNSFW(event.needBlurNSFW); + refreshAdapter(); + } + + @Subscribe + public void onChangeSpoilerBlurEvent(ChangeSpoilerBlurEvent event) { + mAdapter.setBlurSpoiler(event.needBlurSpoiler); + refreshAdapter(); + } + + private void refreshAdapter() { + int previousPosition = -1; + if(mLinearLayoutManager != null) { + previousPosition = mLinearLayoutManager.findFirstVisibleItemPosition(); + } else if(mStaggeredGridLayoutManager != null) { + int[] into = new int[2]; + previousPosition = mStaggeredGridLayoutManager.findFirstVisibleItemPositions(into)[0]; + } + + RecyclerView.LayoutManager layoutManager = mPostRecyclerView.getLayoutManager(); + mPostRecyclerView.setAdapter(null); + mPostRecyclerView.setLayoutManager(null); + mPostRecyclerView.setAdapter(mAdapter); + mPostRecyclerView.setLayoutManager(layoutManager); + + if(previousPosition > 0) { + mPostRecyclerView.scrollToPosition(previousPosition); + } + } + + @Override + public void onStart() { + super.onStart(); + if(isInLazyMode && isLazyModePaused) { + resumeLazyMode(false); + } + } + + @Override + public void onStop() { + super.onStop(); + if(isInLazyMode) { + pauseLazyMode(false); + } + } + + @Override + public void onDestroy() { + EventBus.getDefault().unregister(this); + super.onDestroy(); + } + + private static abstract class LazyModeRunnable implements Runnable { + private int currentPosition = -1; + + int getCurrentPosition() { + return currentPosition; + } + + void setCurrentPosition(int currentPosition) { + this.currentPosition = currentPosition; + } + + void incrementCurrentPosition() { + currentPosition++; + } + + void resetOldPosition() { + currentPosition = -1; + } + } + + private static class StaggeredGridLayoutManagerItemOffsetDecoration extends RecyclerView.ItemDecoration { + + private int mItemOffset; + + StaggeredGridLayoutManagerItemOffsetDecoration(int itemOffset) { + mItemOffset = itemOffset; + } + + StaggeredGridLayoutManagerItemOffsetDecoration(@NonNull Context context, @DimenRes int itemOffsetId) { + this(context.getResources().getDimensionPixelSize(itemOffsetId)); + } + + @Override + public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, + @NonNull RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + + StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams(); + + int spanIndex = layoutParams.getSpanIndex(); + + int halfOffset = mItemOffset / 2; + + if(spanIndex == 0) { + outRect.set(0, 0, halfOffset, 0); + } else { + outRect.set(halfOffset, 0, 0, 0); + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostTypeBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostTypeBottomSheetFragment.java new file mode 100644 index 00000000..8f21ffd0 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostTypeBottomSheetFragment.java @@ -0,0 +1,82 @@ +package ml.docilealligator.infinityforreddit.Fragment; + + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import androidx.fragment.app.Fragment; + +import com.deishelon.roundedbottomsheet.RoundedBottomSheetDialogFragment; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.R; + + +/** + * A simple {@link Fragment} subclass. + */ +public class PostTypeBottomSheetFragment extends RoundedBottomSheetDialogFragment { + + public interface PostTypeSelectionCallback { + void postTypeSelected(int postType); + } + + public static final int TYPE_TEXT = 0; + public static final int TYPE_LINK = 1; + public static final int TYPE_IMAGE = 2; + public static final int TYPE_VIDEO = 3; + + @BindView(R.id.text_type_linear_layout_post_type_bottom_sheet_fragment) LinearLayout textTypeLinearLayout; + @BindView(R.id.link_type_linear_layout_post_type_bottom_sheet_fragment) LinearLayout linkTypeLinearLayout; + @BindView(R.id.image_type_linear_layout_post_type_bottom_sheet_fragment) LinearLayout imageTypeLinearLayout; + @BindView(R.id.video_type_linear_layout_post_type_bottom_sheet_fragment) LinearLayout videoTypeLinearLayout; + + public PostTypeBottomSheetFragment() { + // Required empty public constructor + } + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_post_type_bottom_sheet, container, false); + ButterKnife.bind(this, rootView); + + Activity activity = getActivity(); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O + && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + + textTypeLinearLayout.setOnClickListener(view -> { + ((PostTypeSelectionCallback) activity).postTypeSelected(TYPE_TEXT); + dismiss(); + }); + + linkTypeLinearLayout.setOnClickListener(view -> { + ((PostTypeSelectionCallback) activity).postTypeSelected(TYPE_LINK); + dismiss(); + }); + + imageTypeLinearLayout.setOnClickListener(view -> { + ((PostTypeSelectionCallback) activity).postTypeSelected(TYPE_IMAGE); + dismiss(); + }); + + videoTypeLinearLayout.setOnClickListener(view -> { + ((PostTypeSelectionCallback) activity).postTypeSelected(TYPE_VIDEO); + dismiss(); + }); + + return rootView; + } + +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SearchPostSortTypeBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SearchPostSortTypeBottomSheetFragment.java new file mode 100644 index 00000000..181842d5 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SearchPostSortTypeBottomSheetFragment.java @@ -0,0 +1,84 @@ +package ml.docilealligator.infinityforreddit.Fragment; + + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.fragment.app.Fragment; + +import com.deishelon.roundedbottomsheet.RoundedBottomSheetDialogFragment; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.R; + + +/** + * A simple {@link Fragment} subclass. + */ +public class SearchPostSortTypeBottomSheetFragment extends RoundedBottomSheetDialogFragment { + + public interface SearchSortTypeSelectionCallback { + void searchSortTypeSelected(String sortType); + } + + @BindView(R.id.relevance_type_text_view_search_sort_type_bottom_sheet_fragment) TextView relevanceTypeTextView; + @BindView(R.id.hot_type_text_view_search_sort_type_bottom_sheet_fragment) TextView hotTypeTextView; + @BindView(R.id.top_type_text_view_search_sort_type_bottom_sheet_fragment) TextView topTypeTextView; + @BindView(R.id.new_type_text_view_search_sort_type_bottom_sheet_fragment) TextView newTypeTextView; + @BindView(R.id.comments_type_text_view_search_sort_type_bottom_sheet_fragment) TextView commentsTypeTextView; + + public SearchPostSortTypeBottomSheetFragment() { + // Required empty public constructor + } + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_search_post_sort_type_bottom_sheet, container, false); + ButterKnife.bind(this, rootView); + + Activity activity = getActivity(); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O + && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + + relevanceTypeTextView.setOnClickListener(view -> { + ((SearchSortTypeSelectionCallback) activity).searchSortTypeSelected(PostDataSource.SORT_TYPE_RELEVANCE); + dismiss(); + }); + + hotTypeTextView.setOnClickListener(view -> { + ((SearchSortTypeSelectionCallback) activity).searchSortTypeSelected(PostDataSource.SORT_TYPE_HOT); + dismiss(); + }); + + topTypeTextView.setOnClickListener(view -> { + ((SearchSortTypeSelectionCallback) activity).searchSortTypeSelected(PostDataSource.SORT_TYPE_TOP); + dismiss(); + }); + + newTypeTextView.setOnClickListener(view -> { + ((SearchSortTypeSelectionCallback) activity).searchSortTypeSelected(PostDataSource.SORT_TYPE_NEW); + dismiss(); + }); + + commentsTypeTextView.setOnClickListener(view -> { + ((SearchSortTypeSelectionCallback) activity).searchSortTypeSelected(PostDataSource.SORT_TYPE_COMMENTS); + dismiss(); + }); + + return rootView; + } + +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SearchUserAndSubredditSortTypeBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SearchUserAndSubredditSortTypeBottomSheetFragment.java new file mode 100644 index 00000000..d75a964e --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SearchUserAndSubredditSortTypeBottomSheetFragment.java @@ -0,0 +1,70 @@ +package ml.docilealligator.infinityforreddit.Fragment; + + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.fragment.app.Fragment; + +import com.deishelon.roundedbottomsheet.RoundedBottomSheetDialogFragment; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.R; + + +/** + * A simple {@link Fragment} subclass. + */ +public class SearchUserAndSubredditSortTypeBottomSheetFragment extends RoundedBottomSheetDialogFragment { + + public interface SearchUserAndSubredditSortTypeSelectionCallback { + void searchUserAndSubredditSortTypeSelected(String sortType, int fragmentPosition); + } + + public static final String EXTRA_FRAGMENT_POSITION = "EFP"; + + @BindView(R.id.relevance_type_text_view_search_user_and_subreddit_sort_type_bottom_sheet_fragment) TextView relevanceTypeTextView; + @BindView(R.id.activity_type_text_view_search_user_and_subreddit_sort_type_bottom_sheet_fragment) TextView activityTypeTextView; + + public SearchUserAndSubredditSortTypeBottomSheetFragment() { + // Required empty public constructor + } + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_search_user_and_subreddit_sort_type_bottom_sheet, container, false); + ButterKnife.bind(this, rootView); + + Activity activity = getActivity(); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O + && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + + int position = getArguments().getInt(EXTRA_FRAGMENT_POSITION); + + relevanceTypeTextView.setOnClickListener(view -> { + ((SearchUserAndSubredditSortTypeSelectionCallback) activity).searchUserAndSubredditSortTypeSelected(PostDataSource.SORT_TYPE_RELEVANCE, position); + dismiss(); + }); + + activityTypeTextView.setOnClickListener(view -> { + ((SearchUserAndSubredditSortTypeSelectionCallback) activity).searchUserAndSubredditSortTypeSelected(PostDataSource.SORT_TYPE_HOT, position); + dismiss(); + }); + + return rootView; + } + +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SortTypeBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SortTypeBottomSheetFragment.java new file mode 100644 index 00000000..19305303 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SortTypeBottomSheetFragment.java @@ -0,0 +1,103 @@ +package ml.docilealligator.infinityforreddit.Fragment; + + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; + +import com.deishelon.roundedbottomsheet.RoundedBottomSheetDialogFragment; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.R; + + +/** + * A simple {@link Fragment} subclass. + */ +public class SortTypeBottomSheetFragment extends RoundedBottomSheetDialogFragment { + + public interface SortTypeSelectionCallback { + void sortTypeSelected(String sortType); + } + + public static final String EXTRA_NO_BEST_TYPE = "ENBT"; + + @BindView(R.id.best_type_text_view_sort_type_bottom_sheet_fragment) TextView bestTypeTextView; + @BindView(R.id.hot_type_text_view_sort_type_bottom_sheet_fragment) TextView hotTypeTextView; + @BindView(R.id.new_type_text_view_sort_type_bottom_sheet_fragment) TextView newTypeTextView; + @BindView(R.id.random_type_text_view_sort_type_bottom_sheet_fragment) TextView randomTypeTextView; + @BindView(R.id.rising_type_text_view_sort_type_bottom_sheet_fragment) TextView risingTypeTextView; + @BindView(R.id.top_type_text_view_sort_type_bottom_sheet_fragment) TextView topTypeTextView; + @BindView(R.id.controversial_type_text_view_sort_type_bottom_sheet_fragment) TextView controversialTypeTextView; + + public SortTypeBottomSheetFragment() { + // Required empty public constructor + } + + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_sort_type_bottom_sheet, container, false); + ButterKnife.bind(this, rootView); + + Activity activity = getActivity(); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O + && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + + if(getArguments().getBoolean(EXTRA_NO_BEST_TYPE)) { + bestTypeTextView.setVisibility(View.GONE); + } else { + bestTypeTextView.setOnClickListener(view -> { + ((SortTypeSelectionCallback) activity).sortTypeSelected(PostDataSource.SORT_TYPE_BEST); + dismiss(); + }); + } + + hotTypeTextView.setOnClickListener(view -> { + ((SortTypeSelectionCallback) activity).sortTypeSelected(PostDataSource.SORT_TYPE_HOT); + dismiss(); + }); + + newTypeTextView.setOnClickListener(view -> { + ((SortTypeSelectionCallback) activity).sortTypeSelected(PostDataSource.SORT_TYPE_NEW); + dismiss(); + }); + + randomTypeTextView.setOnClickListener(view -> { + ((SortTypeSelectionCallback) activity).sortTypeSelected(PostDataSource.SORT_TYPE_RANDOM); + dismiss(); + }); + + risingTypeTextView.setOnClickListener(view -> { + ((SortTypeSelectionCallback) activity).sortTypeSelected(PostDataSource.SORT_TYPE_RISING); + dismiss(); + }); + + topTypeTextView.setOnClickListener(view -> { + ((SortTypeSelectionCallback) activity).sortTypeSelected(PostDataSource.SORT_TYPE_TOP); + dismiss(); + }); + + controversialTypeTextView.setOnClickListener(view -> { + ((SortTypeSelectionCallback) activity).sortTypeSelected(PostDataSource.SORT_TYPE_CONTROVERSIAL); + dismiss(); + }); + + return rootView; + } + +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SubredditListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SubredditListingFragment.java new file mode 100644 index 00000000..1d8719de --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SubredditListingFragment.java @@ -0,0 +1,190 @@ +package ml.docilealligator.infinityforreddit.Fragment; + + +import android.app.Activity; +import android.content.Intent; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.Activity.SearchSubredditsResultActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewSubredditDetailActivity; +import ml.docilealligator.infinityforreddit.FragmentCommunicator; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.NetworkState; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.Adapter.SubredditListingRecyclerViewAdapter; +import ml.docilealligator.infinityforreddit.SubredditListingViewModel; +import retrofit2.Retrofit; + + +/** + * A simple {@link Fragment} subclass. + */ +public class SubredditListingFragment extends Fragment implements FragmentCommunicator { + + public static final String EXTRA_QUERY = "EQ"; + public static final String EXTRA_IS_POSTING = "EIP"; + public static final String EXTRA_ACCESS_TOKEN = "EAT"; + public static final String EXTRA_ACCOUNT_NAME = "EAN"; + + @BindView(R.id.coordinator_layout_subreddit_listing_fragment) CoordinatorLayout mCoordinatorLayout; + @BindView(R.id.recycler_view_subreddit_listing_fragment) RecyclerView mSubredditListingRecyclerView; + @BindView(R.id.progress_bar_subreddit_listing_fragment) CircleProgressBar mProgressBar; + @BindView(R.id.fetch_subreddit_listing_info_linear_layout_subreddit_listing_fragment) LinearLayout mFetchSubredditListingInfoLinearLayout; + @BindView(R.id.fetch_subreddit_listing_info_image_view_subreddit_listing_fragment) ImageView mFetchSubredditListingInfoImageView; + @BindView(R.id.fetch_subreddit_listing_info_text_view_subreddit_listing_fragment) TextView mFetchSubredditListingInfoTextView; + + private LinearLayoutManager mLinearLayoutManager; + + private SubredditListingRecyclerViewAdapter mAdapter; + + SubredditListingViewModel mSubredditListingViewModel; + + @Inject @Named("no_oauth") + Retrofit mRetrofit; + + @Inject @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase redditDataRoomDatabase; + + public SubredditListingFragment() { + // Required empty public constructor + } + + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View rootView = inflater.inflate(R.layout.fragment_subreddit_listing, container, false); + + Activity activity = getActivity(); + + ((Infinity) activity.getApplication()).getAppComponent().inject(this); + + ButterKnife.bind(this, rootView); + + Resources resources = getResources(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { + int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); + if (navBarResourceId > 0) { + mSubredditListingRecyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); + } + } + } + + mLinearLayoutManager = new LinearLayoutManager(getActivity()); + mSubredditListingRecyclerView.setLayoutManager(mLinearLayoutManager); + + String query = getArguments().getString(EXTRA_QUERY); + boolean isPosting = getArguments().getBoolean(EXTRA_IS_POSTING); + String accessToken = getArguments().getString(EXTRA_ACCESS_TOKEN); + String accountName = getArguments().getString(EXTRA_ACCOUNT_NAME); + + mAdapter = new SubredditListingRecyclerViewAdapter(activity, mOauthRetrofit, mRetrofit, + accessToken, accountName, redditDataRoomDatabase, + new SubredditListingRecyclerViewAdapter.Callback() { + @Override + public void retryLoadingMore() { + mSubredditListingViewModel.retryLoadingMore(); + } + + @Override + public void subredditSelected(String subredditName, String iconUrl) { + if(isPosting) { + ((SearchSubredditsResultActivity) activity).getSelectedSubreddit(subredditName, iconUrl); + } else { + Intent intent = new Intent(activity, ViewSubredditDetailActivity.class); + intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, subredditName); + activity.startActivity(intent); + } + } + }); + + mSubredditListingRecyclerView.setAdapter(mAdapter); + + SubredditListingViewModel.Factory factory = new SubredditListingViewModel.Factory(mRetrofit, query, + PostDataSource.SORT_TYPE_RELEVANCE); + mSubredditListingViewModel = new ViewModelProvider(this, factory).get(SubredditListingViewModel.class); + mSubredditListingViewModel.getSubreddits().observe(this, subredditData -> mAdapter.submitList(subredditData)); + + mSubredditListingViewModel.hasSubredditLiveData().observe(this, hasSubreddit -> { + mProgressBar.setVisibility(View.GONE); + if(hasSubreddit) { + mFetchSubredditListingInfoLinearLayout.setVisibility(View.GONE); + } else { + mFetchSubredditListingInfoLinearLayout.setOnClickListener(view -> { + //Do nothing + }); + showErrorView(R.string.no_subreddits); + } + }); + + mSubredditListingViewModel.getInitialLoadingState().observe(this, networkState -> { + if(networkState.getStatus().equals(NetworkState.Status.SUCCESS)) { + mProgressBar.setVisibility(View.GONE); + } else if(networkState.getStatus().equals(NetworkState.Status.FAILED)) { + mProgressBar.setVisibility(View.GONE); + mFetchSubredditListingInfoLinearLayout.setOnClickListener(view -> refresh()); + showErrorView(R.string.search_subreddits_error); + } else { + mProgressBar.setVisibility(View.VISIBLE); + } + }); + + mSubredditListingViewModel.getPaginationNetworkState().observe(this, networkState -> { + mAdapter.setNetworkState(networkState); + }); + + return rootView; + } + + private void showErrorView(int stringResId) { + if(getActivity() != null && isAdded()) { + mProgressBar.setVisibility(View.GONE); + mFetchSubredditListingInfoLinearLayout.setVisibility(View.VISIBLE); + mFetchSubredditListingInfoTextView.setText(stringResId); + Glide.with(this).load(R.drawable.error_image).into(mFetchSubredditListingInfoImageView); + } + } + + public void changeSortType(String sortType) { + mSubredditListingViewModel.changeSortType(sortType); + } + + @Override + public void refresh() { + mFetchSubredditListingInfoLinearLayout.setVisibility(View.GONE); + mSubredditListingViewModel.refresh(); + mAdapter.setNetworkState(null); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SubscribedSubredditsListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SubscribedSubredditsListingFragment.java new file mode 100644 index 00000000..e15f325d --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SubscribedSubredditsListingFragment.java @@ -0,0 +1,121 @@ +package ml.docilealligator.infinityforreddit.Fragment; + + +import android.app.Activity; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; + +import javax.inject.Inject; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.Activity.SubredditSelectionActivity; +import ml.docilealligator.infinityforreddit.Adapter.SubscribedSubredditsRecyclerViewAdapter; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditViewModel; + + +/** + * A simple {@link Fragment} subclass. + */ +public class SubscribedSubredditsListingFragment extends Fragment { + + public static final String EXTRA_ACCOUNT_NAME = "EAT"; + public static final String EXTRA_ACCOUNT_PROFILE_IMAGE_URL = "EAPIU"; + public static final String EXTRA_IS_SUBREDDIT_SELECTION = "EISS"; + public static final String EXTRA_EXTRA_CLEAR_SELECTION = "EECS"; + + @BindView(R.id.recycler_view_subscribed_subreddits_listing_fragment) RecyclerView mRecyclerView; + @BindView(R.id.no_subscriptions_linear_layout_subreddits_listing_fragment) LinearLayout mLinearLayout; + @BindView(R.id.no_subscriptions_image_view_subreddits_listing_fragment) ImageView mImageView; + + private Activity mActivity; + + private RequestManager mGlide; + + private SubscribedSubredditViewModel mSubscribedSubredditViewModel; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + public SubscribedSubredditsListingFragment() { + // Required empty public constructor + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_subscribed_subreddits_listing, container, false); + + ButterKnife.bind(this, rootView); + + mActivity = getActivity(); + + ((Infinity) mActivity.getApplication()).getAppComponent().inject(this); + + Resources resources = getResources(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { + int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); + if (navBarResourceId > 0) { + mRecyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); + } + } + } + + String accountName = getArguments().getString(EXTRA_ACCOUNT_NAME); + + mGlide = Glide.with(this); + + mRecyclerView.setLayoutManager(new LinearLayoutManager(mActivity)); + + SubscribedSubredditsRecyclerViewAdapter adapter; + if(getArguments().getBoolean(EXTRA_IS_SUBREDDIT_SELECTION)) { + adapter = new SubscribedSubredditsRecyclerViewAdapter(mActivity, getArguments().getBoolean(EXTRA_EXTRA_CLEAR_SELECTION), + (name, iconUrl, subredditIsUser) -> ((SubredditSelectionActivity) mActivity).getSelectedSubreddit(name, iconUrl, subredditIsUser)); + } else { + adapter = new SubscribedSubredditsRecyclerViewAdapter(mActivity); + } + + mRecyclerView.setAdapter(adapter); + + mSubscribedSubredditViewModel = new ViewModelProvider(this, + new SubscribedSubredditViewModel.Factory(mActivity.getApplication(), mRedditDataRoomDatabase, accountName)) + .get(SubscribedSubredditViewModel.class); + mSubscribedSubredditViewModel.getAllSubscribedSubreddits().observe(this, subscribedSubredditData -> { + if (subscribedSubredditData == null || subscribedSubredditData.size() == 0) { + mRecyclerView.setVisibility(View.GONE); + mLinearLayout.setVisibility(View.VISIBLE); + mGlide.load(R.drawable.error_image).into(mImageView); + } else { + mLinearLayout.setVisibility(View.GONE); + mRecyclerView.setVisibility(View.VISIBLE); + mGlide.clear(mImageView); + } + + adapter.addUser(accountName, getArguments().getString(EXTRA_ACCOUNT_PROFILE_IMAGE_URL)); + adapter.setSubscribedSubreddits(subscribedSubredditData); + }); + + return rootView; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/UserListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/UserListingFragment.java new file mode 100644 index 00000000..8583a754 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/UserListingFragment.java @@ -0,0 +1,167 @@ +package ml.docilealligator.infinityforreddit.Fragment; + + +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.FragmentCommunicator; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.NetworkState; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.Adapter.UserListingRecyclerViewAdapter; +import ml.docilealligator.infinityforreddit.UserListingViewModel; +import retrofit2.Retrofit; + + +/** + * A simple {@link Fragment} subclass. + */ +public class UserListingFragment extends Fragment implements FragmentCommunicator { + + public static final String EXTRA_QUERY = "EQ"; + public static final String EXTRA_ACCESS_TOKEN = "EAT"; + public static final String EXTRA_ACCOUNT_NAME = "EAN"; + + @BindView(R.id.coordinator_layout_user_listing_fragment) CoordinatorLayout mCoordinatorLayout; + @BindView(R.id.recycler_view_user_listing_fragment) RecyclerView mUserListingRecyclerView; + @BindView(R.id.progress_bar_user_listing_fragment) CircleProgressBar mProgressBar; + @BindView(R.id.fetch_user_listing_info_linear_layout_user_listing_fragment) LinearLayout mFetchUserListingInfoLinearLayout; + @BindView(R.id.fetch_user_listing_info_image_view_user_listing_fragment) ImageView mFetchUserListingInfoImageView; + @BindView(R.id.fetch_user_listing_info_text_view_user_listing_fragment) TextView mFetchUserListingInfoTextView; + + private LinearLayoutManager mLinearLayoutManager; + + private String mQuery; + + private UserListingRecyclerViewAdapter mAdapter; + + UserListingViewModel mUserListingViewModel; + + @Inject @Named("no_oauth") + Retrofit mRetrofit; + + @Inject @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase redditDataRoomDatabase; + + public UserListingFragment() { + // Required empty public constructor + } + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View rootView = inflater.inflate(R.layout.fragment_user_listing, container, false); + + ((Infinity) getActivity().getApplication()).getAppComponent().inject(this); + + ButterKnife.bind(this, rootView); + + Resources resources = getResources(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { + int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); + if (navBarResourceId > 0) { + mUserListingRecyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); + } + } + } + + mLinearLayoutManager = new LinearLayoutManager(getActivity()); + mUserListingRecyclerView.setLayoutManager(mLinearLayoutManager); + + mQuery = getArguments().getString(EXTRA_QUERY); + String accessToken = getArguments().getString(EXTRA_ACCESS_TOKEN); + String accountName = getArguments().getString(EXTRA_ACCOUNT_NAME); + + mAdapter = new UserListingRecyclerViewAdapter(getActivity(), mOauthRetrofit, mRetrofit, + accessToken, accountName, redditDataRoomDatabase.subscribedUserDao(), + () -> mUserListingViewModel.retryLoadingMore()); + + mUserListingRecyclerView.setAdapter(mAdapter); + + UserListingViewModel.Factory factory = new UserListingViewModel.Factory(mRetrofit, mQuery, + PostDataSource.SORT_TYPE_RELEVANCE); + mUserListingViewModel = new ViewModelProvider(this, factory).get(UserListingViewModel.class); + mUserListingViewModel.getUsers().observe(this, UserData -> mAdapter.submitList(UserData)); + + mUserListingViewModel.hasUser().observe(this, hasUser -> { + mProgressBar.setVisibility(View.GONE); + if(hasUser) { + mFetchUserListingInfoLinearLayout.setVisibility(View.GONE); + } else { + mFetchUserListingInfoLinearLayout.setOnClickListener(view -> { + //Do nothing + }); + showErrorView(R.string.no_users); + } + }); + + mUserListingViewModel.getInitialLoadingState().observe(this, networkState -> { + if(networkState.getStatus().equals(NetworkState.Status.SUCCESS)) { + mProgressBar.setVisibility(View.GONE); + } else if(networkState.getStatus().equals(NetworkState.Status.FAILED)) { + mProgressBar.setVisibility(View.GONE); + mFetchUserListingInfoLinearLayout.setOnClickListener(view -> refresh()); + showErrorView(R.string.search_users_error); + } else { + mProgressBar.setVisibility(View.VISIBLE); + } + }); + + mUserListingViewModel.getPaginationNetworkState().observe(this, networkState -> { + mAdapter.setNetworkState(networkState); + }); + + return rootView; + } + + private void showErrorView(int stringResId) { + if(getActivity() != null && isAdded()) { + mProgressBar.setVisibility(View.GONE); + mFetchUserListingInfoLinearLayout.setVisibility(View.VISIBLE); + mFetchUserListingInfoTextView.setText(stringResId); + Glide.with(this).load(R.drawable.error_image).into(mFetchUserListingInfoImageView); + } + } + + public void changeSortType(String sortType) { + mUserListingViewModel.changeSortType(sortType); + } + + @Override + public void refresh() { + mFetchUserListingInfoLinearLayout.setVisibility(View.GONE); + mUserListingViewModel.refresh(); + mAdapter.setNetworkState(null); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/UserThingSortTypeBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/UserThingSortTypeBottomSheetFragment.java new file mode 100644 index 00000000..4e9171dc --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/UserThingSortTypeBottomSheetFragment.java @@ -0,0 +1,90 @@ +package ml.docilealligator.infinityforreddit.Fragment; + + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; + +import com.deishelon.roundedbottomsheet.RoundedBottomSheetDialogFragment; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.PostDataSource; +import ml.docilealligator.infinityforreddit.R; + + +/** + * A simple {@link Fragment} subclass. + */ +public class UserThingSortTypeBottomSheetFragment extends RoundedBottomSheetDialogFragment { + + public interface UserThingSortTypeSelectionCallback { + void userThingSortTypeSelected(String sortType); + } + + static final String EXTRA_NO_BEST_TYPE = "ENBT"; + + @BindView(R.id.new_type_text_view_user_thing_sort_type_bottom_sheet_fragment) TextView newTypeTextView; + @BindView(R.id.hot_type_text_view_user_thing_sort_type_bottom_sheet_fragment) TextView hotTypeTextView; + @BindView(R.id.top_type_text_view_user_thing_sort_type_bottom_sheet_fragment) TextView topTypeTextView; + @BindView(R.id.controversial_type_text_view_user_thing_sort_type_bottom_sheet_fragment) TextView controversialTypeTextView; + + public UserThingSortTypeBottomSheetFragment() { + // Required empty public constructor + } + + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_user_thing_sort_type_bottom_sheet, container, false); + + ButterKnife.bind(this, rootView); + + Activity activity = getActivity(); + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O + && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + + newTypeTextView.setOnClickListener(view -> { + if(activity != null) { + ((UserThingSortTypeSelectionCallback) activity).userThingSortTypeSelected(PostDataSource.SORT_TYPE_NEW); + } + dismiss(); + }); + + hotTypeTextView.setOnClickListener(view -> { + if(activity != null) { + ((UserThingSortTypeSelectionCallback) activity).userThingSortTypeSelected(PostDataSource.SORT_TYPE_HOT); + } + dismiss(); + }); + + topTypeTextView.setOnClickListener(view -> { + if(activity != null) { + ((UserThingSortTypeSelectionCallback) activity).userThingSortTypeSelected(PostDataSource.SORT_TYPE_TOP); + } + dismiss(); + }); + + controversialTypeTextView.setOnClickListener(view -> { + if(activity != null) { + ((UserThingSortTypeSelectionCallback) activity).userThingSortTypeSelected(PostDataSource.SORT_TYPE_CONTROVERSIAL); + } + dismiss(); + }); + + return rootView; + } + +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FragmentCommunicator.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FragmentCommunicator.java index c50ef12c..e6fc019f 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FragmentCommunicator.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FragmentCommunicator.java @@ -1,6 +1,6 @@ package ml.docilealligator.infinityforreddit; -interface FragmentCommunicator { +public interface FragmentCommunicator { void refresh(); default void changeNSFW(boolean nsfw) {}; default boolean startLazyMode() { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/GetCurrentAccountAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/GetCurrentAccountAsyncTask.java deleted file mode 100644 index 752c596a..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/GetCurrentAccountAsyncTask.java +++ /dev/null @@ -1,33 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.AsyncTask; - -import ml.docilealligator.infinityforreddit.Account.Account; -import ml.docilealligator.infinityforreddit.Account.AccountDao; - -class GetCurrentAccountAsyncTask extends AsyncTask { - - interface GetCurrentAccountAsyncTaskListener { - void success(Account account); - } - - Account account; - AccountDao accountDao; - GetCurrentAccountAsyncTaskListener getCurrentAccountAsyncTaskListener; - - GetCurrentAccountAsyncTask(AccountDao accountDao, GetCurrentAccountAsyncTaskListener getCurrentAccountAsyncTaskListener) { - this.accountDao = accountDao; - this.getCurrentAccountAsyncTaskListener = getCurrentAccountAsyncTaskListener; - } - - @Override - protected Void doInBackground(Void... voids) { - account = accountDao.getCurrentAccount(); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - getCurrentAccountAsyncTaskListener.success(account); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/HidePost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/HidePost.java index ec6770d2..0ecee1bf 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/HidePost.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/HidePost.java @@ -10,14 +10,14 @@ import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; -class HidePost { - interface HidePostListener { +public class HidePost { + public interface HidePostListener { void success(); void failed(); } - static void hidePost(Retrofit oauthRetrofit, String accessToken, String fullname, - HidePostListener hidePostListener) { + public static void hidePost(Retrofit oauthRetrofit, String accessToken, String fullname, + HidePostListener hidePostListener) { Map params = new HashMap<>(); params.put(RedditUtils.ID_KEY, fullname); oauthRetrofit.create(RedditAPI.class).hide(RedditUtils.getOAuthHeader(accessToken), params).enqueue(new Callback() { @@ -37,8 +37,8 @@ class HidePost { }); } - static void unhidePost(Retrofit oauthRetrofit, String accessToken, String fullname, - HidePostListener hidePostListener) { + public static void unhidePost(Retrofit oauthRetrofit, String accessToken, String fullname, + HidePostListener hidePostListener) { Map params = new HashMap<>(); params.put(RedditUtils.ID_KEY, fullname); oauthRetrofit.create(RedditAPI.class).unhide(RedditUtils.getOAuthHeader(accessToken), params).enqueue(new Callback() { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/InsertSubscribedThingsAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/InsertSubscribedThingsAsyncTask.java deleted file mode 100644 index 2cb1e45e..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/InsertSubscribedThingsAsyncTask.java +++ /dev/null @@ -1,79 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.AsyncTask; - -import androidx.annotation.Nullable; - -import java.util.List; - -import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditDao; -import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditData; -import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditDao; -import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditData; -import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserDao; -import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserData; - -class InsertSubscribedThingsAsyncTask extends AsyncTask { - - interface InsertSubscribedThingListener { - void insertSuccess(); - } - - private RedditDataRoomDatabase mRedditDataRoomDatabase; - private String mAccountName; - private SubscribedSubredditDao mSubscribedSubredditDao; - private SubscribedUserDao mUserDao; - private SubredditDao mSubredditDao; - private List subscribedSubredditData; - private List subscribedUserData; - private List subredditData; - private InsertSubscribedThingListener insertSubscribedThingListener; - - InsertSubscribedThingsAsyncTask(RedditDataRoomDatabase redditDataRoomDatabase, @Nullable String accountName, - List subscribedSubredditData, - List subscribedUserData, - List subredditData, - InsertSubscribedThingListener insertSubscribedThingListener) { - mRedditDataRoomDatabase = redditDataRoomDatabase; - mAccountName = accountName; - mSubscribedSubredditDao = redditDataRoomDatabase.subscribedSubredditDao(); - mUserDao = redditDataRoomDatabase.subscribedUserDao(); - mSubredditDao = redditDataRoomDatabase.subredditDao(); - - this.subscribedSubredditData = subscribedSubredditData; - this.subscribedUserData = subscribedUserData; - this.subredditData = subredditData; - this.insertSubscribedThingListener = insertSubscribedThingListener; - } - - @Override - protected Void doInBackground(final Void... params) { - if(mAccountName != null && mRedditDataRoomDatabase.accountDao().getAccountData(mAccountName) == null) { - return null; - } - - if(subscribedSubredditData != null) { - for (SubscribedSubredditData s : subscribedSubredditData) { - mSubscribedSubredditDao.insert(s); - } - } - - if(subscribedUserData != null) { - for (SubscribedUserData s : subscribedUserData) { - mUserDao.insert(s); - } - } - - if(subredditData != null) { - for (SubredditData s : subredditData) { - mSubredditDao.insert(s); - } - } - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - insertSubscribedThingListener.insertSuccess(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/InsertUserDataAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/InsertUserDataAsyncTask.java deleted file mode 100644 index 90ea800b..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/InsertUserDataAsyncTask.java +++ /dev/null @@ -1,36 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.AsyncTask; - -import ml.docilealligator.infinityforreddit.User.UserData; -import ml.docilealligator.infinityforreddit.User.UserDao; - -public class InsertUserDataAsyncTask extends AsyncTask { - private UserDao userDao; - private UserData userData; - private InsertUserDataCallback insertUserDataCallback; - - public interface InsertUserDataCallback { - void insertSuccess(); - } - - public InsertUserDataAsyncTask(UserDao userDao, UserData userData, InsertUserDataCallback insertUserDataCallback) { - this.userDao = userDao; - this.userData = userData; - this.insertUserDataCallback = insertUserDataCallback; - } - - @Override - protected Void doInBackground(Void... voids) { - userDao.insert(userData); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - if(insertUserDataCallback != null) { - insertUserDataCallback.insertSuccess(); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/JSONUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/JSONUtils.java index 269e4f41..1e73bcb2 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/JSONUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/JSONUtils.java @@ -5,84 +5,84 @@ package ml.docilealligator.infinityforreddit; */ public class JSONUtils { - static final String KIND_KEY = "kind"; - static final String DATA_KEY = "data"; - static final String AFTER_KEY = "after"; - static final String CHILDREN_KEY = "children"; - static final String COUNT_KEY = "count"; - static final String TITLE_KEY = "title"; - static final String NAME_KEY = "name"; - static final String SUBREDDIT_NAME_PREFIX_KEY = "subreddit_name_prefixed"; - static final String SELFTEXT_KEY = "selftext"; - static final String AUTHOR_KEY = "author"; - static final String LINK_AUTHOR_KEY = "link_author"; - static final String LINK_FLAIR_TEXT_KEY = "link_flair_text"; - static final String SCORE_KEY = "score"; - static final String LIKES_KEY = "likes"; - static final String NSFW_KEY = "over_18"; - static final String GILDED_KEY = "gilded"; - static final String PERMALINK_KEY = "permalink"; - static final String CREATED_UTC_KEY = "created_utc"; - static final String PREVIEW_KEY = "preview"; - static final String IMAGES_KEY = "images"; - static final String WIDTH_KEY = "width"; - static final String HEIGHT_KEY = "height"; - static final String VARIANTS_KEY = "variants"; - static final String GIF_KEY = "gif"; - static final String MP4_KEY = "mp4"; - static final String SOURCE_KEY = "source"; - static final String URL_KEY = "url"; - static final String MEDIA_KEY = "media"; - static final String REDDIT_VIDEO_KEY = "reddit_video"; - static final String HLS_URL_KEY = "hls_url"; - static final String IS_VIDEO_KEY = "is_video"; - static final String CROSSPOST_PARENT_LIST = "crosspost_parent_list"; - static final String REDDIT_VIDEO_PREVIEW_KEY = "reddit_video_preview"; - static final String STICKIED_KEY = "stickied"; - static final String BODY_KEY = "body"; - static final String COLLAPSED_KEY = "collapsed"; - static final String IS_SUBMITTER_KEY = "is_submitter"; - static final String REPLIES_KEY = "replies"; - static final String DEPTH_KEY = "depth"; - static final String ID_KEY = "id"; - static final String SCORE_HIDDEN_KEY = "score_hidden"; - static final String SUBREDDIT_KEY = "subreddit"; - static final String BANNER_IMG_KEY = "banner_img"; - static final String BANNER_BACKGROUND_IMAGE_KEY = "banner_background_image"; - static final String ICON_IMG_KEY = "icon_img"; - static final String COMMUNITY_ICON_KEY = "community_icon"; - static final String LINK_KARMA_KEY = "link_karma"; - static final String COMMENT_KARMA_KEY = "comment_karma"; - static final String DISPLAY_NAME = "display_name"; - static final String SUBREDDIT_TYPE_KEY = "subreddit_type"; - static final String SUBREDDIT_TYPE_VALUE_USER = "user"; - static final String SUBSCRIBERS_KEY = "subscribers"; - static final String PUBLIC_DESCRIPTION_KEY = "public_description"; - static final String ACTIVE_USER_COUNT_KEY = "active_user_count"; - static final String IS_GOLD_KEY = "is_gold"; - static final String IS_FRIEND_KEY = "is_friend"; - static final String JSON_KEY = "json"; - static final String PARENT_ID_KEY = "parent_id"; - static final String LINK_ID_KEY = "link_id"; - static final String LINK_TITLE_KEY = "link_title"; - static final String ERRORS_KEY = "errors"; - static final String ARGS_KEY = "args"; - static final String FIELDS_KEY = "fields"; - static final String VALUE_KEY = "value"; - static final String TEXT_KEY = "text"; - static final String SPOILER_KEY = "spoiler"; - static final String RULES_KEY = "rules"; - static final String SHORT_NAME_KEY = "short_name"; - static final String DESCRIPTION_KEY = "description"; - static final String ARCHIVED_KEY = "archived"; - static final String LOCKEC_KEY = "locked"; - static final String SAVED_KEY = "saved"; - static final String TEXT_EDITABLE_KEY = "text_editable"; - static final String SUBJECT_KEY = "subject"; - static final String CONTEXT_KEY = "context"; - static final String DISTINGUISHED_KEY = "distinguished"; - static final String WAS_COMMENT_KEY = "was_comment"; - static final String NEW_KEY = "new"; - static final String NUM_COMMENTS_KEY = "num_comments"; - static final String HIDDEN_KEY = "hidden"; + public static final String KIND_KEY = "kind"; + public static final String DATA_KEY = "data"; + public static final String AFTER_KEY = "after"; + public static final String CHILDREN_KEY = "children"; + public static final String COUNT_KEY = "count"; + public static final String TITLE_KEY = "title"; + public static final String NAME_KEY = "name"; + public static final String SUBREDDIT_NAME_PREFIX_KEY = "subreddit_name_prefixed"; + public static final String SELFTEXT_KEY = "selftext"; + public static final String AUTHOR_KEY = "author"; + public static final String LINK_AUTHOR_KEY = "link_author"; + public static final String LINK_FLAIR_TEXT_KEY = "link_flair_text"; + public static final String SCORE_KEY = "score"; + public static final String LIKES_KEY = "likes"; + public static final String NSFW_KEY = "over_18"; + public static final String GILDED_KEY = "gilded"; + public static final String PERMALINK_KEY = "permalink"; + public static final String CREATED_UTC_KEY = "created_utc"; + public static final String PREVIEW_KEY = "preview"; + public static final String IMAGES_KEY = "images"; + public static final String WIDTH_KEY = "width"; + public static final String HEIGHT_KEY = "height"; + public static final String VARIANTS_KEY = "variants"; + public static final String GIF_KEY = "gif"; + public static final String MP4_KEY = "mp4"; + public static final String SOURCE_KEY = "source"; + public static final String URL_KEY = "url"; + public static final String MEDIA_KEY = "media"; + public static final String REDDIT_VIDEO_KEY = "reddit_video"; + public static final String HLS_URL_KEY = "hls_url"; + public static final String IS_VIDEO_KEY = "is_video"; + public static final String CROSSPOST_PARENT_LIST = "crosspost_parent_list"; + public static final String REDDIT_VIDEO_PREVIEW_KEY = "reddit_video_preview"; + public static final String STICKIED_KEY = "stickied"; + public static final String BODY_KEY = "body"; + public static final String COLLAPSED_KEY = "collapsed"; + public static final String IS_SUBMITTER_KEY = "is_submitter"; + public static final String REPLIES_KEY = "replies"; + public static final String DEPTH_KEY = "depth"; + public static final String ID_KEY = "id"; + public static final String SCORE_HIDDEN_KEY = "score_hidden"; + public static final String SUBREDDIT_KEY = "subreddit"; + public static final String BANNER_IMG_KEY = "banner_img"; + public static final String BANNER_BACKGROUND_IMAGE_KEY = "banner_background_image"; + public static final String ICON_IMG_KEY = "icon_img"; + public static final String COMMUNITY_ICON_KEY = "community_icon"; + public static final String LINK_KARMA_KEY = "link_karma"; + public static final String COMMENT_KARMA_KEY = "comment_karma"; + public static final String DISPLAY_NAME = "display_name"; + public static final String SUBREDDIT_TYPE_KEY = "subreddit_type"; + public static final String SUBREDDIT_TYPE_VALUE_USER = "user"; + public static final String SUBSCRIBERS_KEY = "subscribers"; + public static final String PUBLIC_DESCRIPTION_KEY = "public_description"; + public static final String ACTIVE_USER_COUNT_KEY = "active_user_count"; + public static final String IS_GOLD_KEY = "is_gold"; + public static final String IS_FRIEND_KEY = "is_friend"; + public static final String JSON_KEY = "json"; + public static final String PARENT_ID_KEY = "parent_id"; + public static final String LINK_ID_KEY = "link_id"; + public static final String LINK_TITLE_KEY = "link_title"; + public static final String ERRORS_KEY = "errors"; + public static final String ARGS_KEY = "args"; + public static final String FIELDS_KEY = "fields"; + public static final String VALUE_KEY = "value"; + public static final String TEXT_KEY = "text"; + public static final String SPOILER_KEY = "spoiler"; + public static final String RULES_KEY = "rules"; + public static final String SHORT_NAME_KEY = "short_name"; + public static final String DESCRIPTION_KEY = "description"; + public static final String ARCHIVED_KEY = "archived"; + public static final String LOCKEC_KEY = "locked"; + public static final String SAVED_KEY = "saved"; + public static final String TEXT_EDITABLE_KEY = "text_editable"; + public static final String SUBJECT_KEY = "subject"; + public static final String CONTEXT_KEY = "context"; + public static final String DISTINGUISHED_KEY = "distinguished"; + public static final String WAS_COMMENT_KEY = "was_comment"; + public static final String NEW_KEY = "new"; + public static final String NUM_COMMENTS_KEY = "num_comments"; + public static final String HIDDEN_KEY = "hidden"; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/LinkResolverActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/LinkResolverActivity.java deleted file mode 100644 index 8c5cde11..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/LinkResolverActivity.java +++ /dev/null @@ -1,211 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.ActivityNotFoundException; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.widget.Toast; - -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.browser.customtabs.CustomTabsIntent; - -import java.util.ArrayList; -import java.util.List; - -import javax.inject.Inject; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; -import static androidx.browser.customtabs.CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION; - -public class LinkResolverActivity extends AppCompatActivity { - - static final String EXTRA_MESSAGE_FULLNAME = "ENF"; - static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; - - private static final String POST_PATTERN = "/r/\\w+/comments/\\w+/{0,1}\\w+/{0,1}"; - private static final String COMMENT_PATTERN = "/r/\\w+/comments/\\w+/{0,1}\\w+/\\w+/{0,1}"; - private static final String SUBREDDIT_PATTERN = "/r/\\w+/{0,1}"; - private static final String USER_PATTERN_1 = "/user/\\w+/{0,1}"; - private static final String USER_PATTERN_2 = "/u/\\w+/{0,1}"; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - Uri uri = getIntent().getData(); - if(uri == null) { - Toast.makeText(this, R.string.no_link_available, Toast.LENGTH_SHORT).show(); - finish(); - } else { - String path = uri.getPath(); - if(path == null) { - deepLinkError(uri); - } else { - if(path.endsWith("/")) { - path = path.substring(0, path.length() - 1); - } - - String messageFullname = getIntent().getStringExtra(EXTRA_MESSAGE_FULLNAME); - String newAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); - - if(path.matches(POST_PATTERN)) { - List segments = uri.getPathSegments(); - int commentsIndex = segments.lastIndexOf("comments"); - if(commentsIndex >=0 && commentsIndex < segments.size() - 1) { - Intent intent = new Intent(this, ViewPostDetailActivity.class); - intent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, segments.get(commentsIndex + 1)); - intent.putExtra(ViewPostDetailActivity.EXTRA_MESSAGE_FULLNAME, messageFullname); - intent.putExtra(ViewPostDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); - startActivity(intent); - } else { - deepLinkError(uri); - } - } else if(path.matches(COMMENT_PATTERN)) { - List segments = uri.getPathSegments(); - int commentsIndex = segments.lastIndexOf("comments"); - if(commentsIndex >=0 && commentsIndex < segments.size() - 1) { - Intent intent = new Intent(this, ViewPostDetailActivity.class); - intent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, segments.get(commentsIndex + 1)); - intent.putExtra(ViewPostDetailActivity.EXTRA_SINGLE_COMMENT_ID, segments.get(segments.size() - 1)); - intent.putExtra(ViewPostDetailActivity.EXTRA_MESSAGE_FULLNAME, messageFullname); - intent.putExtra(ViewPostDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); - startActivity(intent); - } else { - deepLinkError(uri); - } - } else if(path.matches(SUBREDDIT_PATTERN)) { - String subredditName = path.substring(3); - if(subredditName.equals("popular") || subredditName.equals("all")) { - Intent intent = new Intent(this, MainActivity.class); - intent.putExtra(MainActivity.EXTRA_POST_TYPE, subredditName); - intent.putExtra(MainActivity.EXTRA_MESSSAGE_FULLNAME, messageFullname); - intent.putExtra(MainActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); - startActivity(intent); - } else { - Intent intent = new Intent(this, ViewSubredditDetailActivity.class); - intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, path.substring(3)); - intent.putExtra(ViewSubredditDetailActivity.EXTRA_MESSAGE_FULLNAME, messageFullname); - intent.putExtra(ViewSubredditDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); - startActivity(intent); - } - } else if(path.matches(USER_PATTERN_1)) { - Intent intent = new Intent(this, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, path.substring(6)); - intent.putExtra(ViewUserDetailActivity.EXTRA_MESSAGE_FULLNAME, messageFullname); - intent.putExtra(ViewUserDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); - startActivity(intent); - } else if(path.matches(USER_PATTERN_2)) { - Intent intent = new Intent(this, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, path.substring(3)); - intent.putExtra(ViewUserDetailActivity.EXTRA_MESSAGE_FULLNAME, messageFullname); - intent.putExtra(ViewUserDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); - startActivity(intent); - } else { - deepLinkError(uri); - } - } - - finish(); - } - } - - private void deepLinkError(Uri uri) { - PackageManager pm = getPackageManager(); - ArrayList resolveInfos = getCustomTabsPackages(pm); - if(!resolveInfos.isEmpty()) { - CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); - // add share action to menu list - builder.addDefaultShareMenuItem(); - builder.setToolbarColor(getResources().getColor(R.color.colorPrimary)); - CustomTabsIntent customTabsIntent = builder.build(); - customTabsIntent.intent.setPackage(resolveInfos.get(0).activityInfo.packageName); - if(uri.getScheme() == null) { - uri = Uri.parse("http://" + uri.toString()); - } - try { - customTabsIntent.launchUrl(this, uri); - } catch (ActivityNotFoundException e) { - openInBrowser(uri, pm); - } - } else { - openInBrowser(uri, pm); - } - } - - private ArrayList getCustomTabsPackages(PackageManager pm) { - // Get default VIEW intent handler. - Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.example.com")); - - // Get all apps that can handle VIEW intents. - List resolvedActivityList = pm.queryIntentActivities(activityIntent, 0); - ArrayList packagesSupportingCustomTabs = new ArrayList<>(); - for (ResolveInfo info : resolvedActivityList) { - Intent serviceIntent = new Intent(); - serviceIntent.setAction(ACTION_CUSTOM_TABS_CONNECTION); - serviceIntent.setPackage(info.activityInfo.packageName); - // Check if this package also resolves the Custom Tabs service. - if (pm.resolveService(serviceIntent, 0) != null) { - packagesSupportingCustomTabs.add(info); - } - } - return packagesSupportingCustomTabs; - } - - private void openInBrowser(Uri uri, PackageManager pm) { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(uri); - - List activities = pm.queryIntentActivities(intent, 0); - ArrayList packageNames = new ArrayList<>(); - - String currentPackageName = getApplicationContext().getPackageName(); - - for(ResolveInfo info : activities) { - if(!info.activityInfo.packageName.equals(currentPackageName)) { - packageNames.add(info.activityInfo.packageName); - } - } - - if(!packageNames.isEmpty()) { - intent.setPackage(packageNames.get(0)); - startActivity(intent); - } else { - Toast.makeText(this, R.string.no_browser_found, Toast.LENGTH_SHORT).show(); - } - } - - public static Uri getRedditUriByPath(String path) { - return Uri.parse("https://www.reddit.com" + path); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/LoadSubredditIconAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/LoadSubredditIconAsyncTask.java deleted file mode 100644 index 0e8f384c..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/LoadSubredditIconAsyncTask.java +++ /dev/null @@ -1,70 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.AsyncTask; - -import java.util.ArrayList; - -import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditDao; -import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditData; -import retrofit2.Retrofit; - -class LoadSubredditIconAsyncTask extends AsyncTask { - interface LoadSubredditIconAsyncTaskListener { - void loadIconSuccess(String iconImageUrl); - } - - private RedditDataRoomDatabase redditDataRoomDatabase; - private SubredditDao subredditDao; - private String subredditName; - private Retrofit retrofit; - private String iconImageUrl; - private boolean hasSubredditInDb; - private LoadSubredditIconAsyncTaskListener loadSubredditIconAsyncTaskListener; - - LoadSubredditIconAsyncTask(RedditDataRoomDatabase redditDataRoomDatabase, String subredditName, Retrofit retrofit, - LoadSubredditIconAsyncTaskListener loadSubredditIconAsyncTaskListener) { - this.redditDataRoomDatabase = redditDataRoomDatabase; - this.subredditDao = redditDataRoomDatabase.subredditDao(); - this.subredditName = subredditName; - this.retrofit = retrofit; - this.loadSubredditIconAsyncTaskListener = loadSubredditIconAsyncTaskListener; - } - - @Override - protected Void doInBackground(Void... voids) { - SubredditData subredditData = subredditDao.getSubredditData(subredditName); - if(subredditData != null) { - iconImageUrl = subredditDao.getSubredditData(subredditName).getIconUrl(); - hasSubredditInDb = true; - } else { - hasSubredditInDb = false; - } - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - if(!isCancelled()) { - if(hasSubredditInDb) { - loadSubredditIconAsyncTaskListener.loadIconSuccess(iconImageUrl); - } else { - FetchSubredditData.fetchSubredditData(retrofit, subredditName, new FetchSubredditData.FetchSubredditDataListener() { - @Override - public void onFetchSubredditDataSuccess(SubredditData subredditData, int nCurrentOnlineSubscribers) { - ArrayList singleSubredditDataList = new ArrayList<>(); - singleSubredditDataList.add(subredditData); - new InsertSubscribedThingsAsyncTask(redditDataRoomDatabase, null, - null, null, singleSubredditDataList, - () -> loadSubredditIconAsyncTaskListener.loadIconSuccess(subredditData.getIconUrl())).execute(); - } - - @Override - public void onFetchSubredditDataFail() { - loadSubredditIconAsyncTaskListener.loadIconSuccess(null); - } - }); - } - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/LoadUserDataAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/LoadUserDataAsyncTask.java deleted file mode 100644 index b9dddf1d..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/LoadUserDataAsyncTask.java +++ /dev/null @@ -1,58 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.AsyncTask; - -import ml.docilealligator.infinityforreddit.User.UserData; -import ml.docilealligator.infinityforreddit.User.UserDao; -import retrofit2.Retrofit; - -public class LoadUserDataAsyncTask extends AsyncTask { - interface LoadUserDataAsyncTaskListener { - void loadUserDataSuccess(String iconImageUrl); - } - - private UserDao userDao; - private String userName; - private String iconImageUrl; - private boolean hasUserInDb; - private Retrofit retrofit; - private LoadUserDataAsyncTaskListener loadUserDataAsyncTaskListener; - - LoadUserDataAsyncTask(UserDao userDao, String userName, Retrofit retrofit, LoadUserDataAsyncTaskListener loadUserDataAsyncTaskListener) { - this.userDao = userDao; - this.userName = userName; - this.retrofit = retrofit; - this.loadUserDataAsyncTaskListener = loadUserDataAsyncTaskListener; - } - - @Override - protected Void doInBackground(Void... voids) { - if(userDao.getUserData(userName) != null) { - iconImageUrl = userDao.getUserData(userName).getIconUrl(); - hasUserInDb = true; - } else { - hasUserInDb = false; - } - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - if(hasUserInDb) { - loadUserDataAsyncTaskListener.loadUserDataSuccess(iconImageUrl); - } else { - FetchUserData.fetchUserData(retrofit, userName, new FetchUserData.FetchUserDataListener() { - @Override - public void onFetchUserDataSuccess(UserData userData) { - new InsertUserDataAsyncTask(userDao, userData, () -> loadUserDataAsyncTaskListener.loadUserDataSuccess(userData.getIconUrl())).execute(); - } - - @Override - public void onFetchUserDataFailed() { - loadUserDataAsyncTaskListener.loadUserDataSuccess(null); - } - }); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/LoginActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/LoginActivity.java deleted file mode 100644 index fc19b2c4..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/LoginActivity.java +++ /dev/null @@ -1,223 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.app.Activity; -import android.content.Intent; -import android.content.SharedPreferences; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.view.MenuItem; -import android.webkit.CookieManager; -import android.webkit.WebView; -import android.webkit.WebViewClient; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.HashMap; -import java.util.Map; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class LoginActivity extends AppCompatActivity { - - @BindView(R.id.toolbar_login_activity) Toolbar toolbar; - - private String authCode; - - @Inject - @Named("no_oauth") - Retrofit mRetrofit; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_login); - - ButterKnife.bind(this); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - setSupportActionBar(toolbar); - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - WebView webView = findViewById(R.id.webview_login_activity); - webView.getSettings().setJavaScriptEnabled(true); - webView.getSettings().setDomStorageEnabled(true); - - Uri baseUri = Uri.parse(RedditUtils.OAUTH_URL); - Uri.Builder uriBuilder = baseUri.buildUpon(); - uriBuilder.appendQueryParameter(RedditUtils.CLIENT_ID_KEY, RedditUtils.CLIENT_ID); - uriBuilder.appendQueryParameter(RedditUtils.RESPONSE_TYPE_KEY, RedditUtils.RESPONSE_TYPE); - uriBuilder.appendQueryParameter(RedditUtils.STATE_KEY, RedditUtils.STATE); - uriBuilder.appendQueryParameter(RedditUtils.REDIRECT_URI_KEY, RedditUtils.REDIRECT_URI); - uriBuilder.appendQueryParameter(RedditUtils.DURATION_KEY, RedditUtils.DURATION); - uriBuilder.appendQueryParameter(RedditUtils.SCOPE_KEY, RedditUtils.SCOPE); - - String url = uriBuilder.toString(); - - CookieManager.getInstance().removeAllCookies(aBoolean -> {}); - - webView.loadUrl(url); - webView.setWebViewClient(new WebViewClient() { - @Override - public boolean shouldOverrideUrlLoading(WebView view, String url) { - if(url.contains("&code=") || url.contains("?code=")) { - Uri uri = Uri.parse(url); - String state = uri.getQueryParameter("state"); - if(state.equals(RedditUtils.STATE)) { - authCode = uri.getQueryParameter("code"); - - Map params = new HashMap<>(); - params.put(RedditUtils.GRANT_TYPE_KEY, "authorization_code"); - params.put("code", authCode); - params.put("redirect_uri", RedditUtils.REDIRECT_URI); - - RedditAPI api = mRetrofit.create(RedditAPI.class); - Call accessTokenCall = api.getAccessToken(RedditUtils.getHttpBasicAuthHeader(), params); - accessTokenCall.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if(response.isSuccessful()) { - try { - String accountResponse = response.body(); - if(accountResponse == null) { - //Handle error - return; - } - - JSONObject responseJSON = new JSONObject(accountResponse); - String accessToken = responseJSON.getString(RedditUtils.ACCESS_TOKEN_KEY); - String refreshToken = responseJSON.getString(RedditUtils.REFRESH_TOKEN_KEY); - - FetchMyInfo.fetchAccountInfo(mOauthRetrofit, accessToken, new FetchMyInfo.FetchUserMyListener() { - @Override - public void onFetchMyInfoSuccess(String response) { - ParseAndSaveAccountInfo.parseAndSaveAccountInfo(response, mRedditDataRoomDatabase, new ParseAndSaveAccountInfo.ParseAndSaveAccountInfoListener() { - @Override - public void onParseMyInfoSuccess(String name, String profileImageUrl, String bannerImageUrl, int karma) { - new ParseAndInsertNewAccountAsyncTask(name, accessToken, refreshToken, profileImageUrl, bannerImageUrl, - karma, authCode, mRedditDataRoomDatabase.accountDao(), - () -> { - Intent resultIntent = new Intent(); - setResult(Activity.RESULT_OK, resultIntent); - finish(); - }).execute(); - } - - @Override - public void onParseMyInfoFail() { - Toast.makeText(LoginActivity.this, R.string.parse_user_info_error, Toast.LENGTH_SHORT).show(); - finish(); - } - }); - } - - @Override - public void onFetchMyInfoFail() { - Toast.makeText(LoginActivity.this, R.string.cannot_fetch_user_info, Toast.LENGTH_SHORT).show(); - finish(); - } - }); - } catch (JSONException e) { - e.printStackTrace(); - Toast.makeText(LoginActivity.this, R.string.parse_json_response_error, Toast.LENGTH_SHORT).show(); - finish(); - } - } else { - Toast.makeText(LoginActivity.this, R.string.retrieve_token_error, Toast.LENGTH_SHORT).show(); - finish(); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - Toast.makeText(LoginActivity.this, R.string.retrieve_token_error, Toast.LENGTH_SHORT).show(); - finish(); - } - }); - } else { - Toast.makeText(LoginActivity.this, R.string.something_went_wrong, Toast.LENGTH_SHORT).show(); - finish(); - } - - } else if (url.contains("error=access_denied")) { - Toast.makeText(LoginActivity.this, R.string.access_denied, Toast.LENGTH_SHORT).show(); - finish(); - } else { - view.loadUrl(url); - } - - return true; - } - - @Override - public void onPageStarted(WebView view, String url, Bitmap favicon) { - super.onPageStarted(view, url, favicon); - } - - @Override - public void onPageFinished(WebView view, String url) { - super.onPageFinished(view, url); - } - }); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - finish(); - return true; - } - return false; - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java deleted file mode 100644 index dd18b59e..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java +++ /dev/null @@ -1,1221 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.app.Activity; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.ActionBarDrawerToggle; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.core.view.GravityCompat; -import androidx.core.widget.NestedScrollView; -import androidx.drawerlayout.widget.DrawerLayout; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentPagerAdapter; -import androidx.lifecycle.ViewModelProvider; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import androidx.viewpager.widget.ViewPager; -import androidx.work.Constraints; -import androidx.work.ExistingPeriodicWorkPolicy; -import androidx.work.NetworkType; -import androidx.work.PeriodicWorkRequest; -import androidx.work.WorkManager; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.bumptech.glide.request.RequestOptions; -import com.google.android.material.appbar.AppBarLayout; -import com.google.android.material.appbar.CollapsingToolbarLayout; -import com.google.android.material.floatingactionbutton.FloatingActionButton; -import com.google.android.material.tabs.TabLayout; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import java.util.ArrayList; -import java.util.concurrent.TimeUnit; - -import javax.inject.Inject; -import javax.inject.Named; - -import ml.docilealligator.infinityforreddit.Account.Account; -import ml.docilealligator.infinityforreddit.Account.AccountViewModel; -import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditData; -import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditData; -import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserData; -import butterknife.BindView; -import butterknife.ButterKnife; -import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import pl.droidsonroids.gif.GifImageView; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class MainActivity extends AppCompatActivity implements SortTypeBottomSheetFragment.SortTypeSelectionCallback, - PostTypeBottomSheetFragment.PostTypeSelectionCallback { - - static final String EXTRA_POST_TYPE = "EPT"; - static final String EXTRA_MESSSAGE_FULLNAME = "ENF"; - static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; - - private static final String FETCH_USER_INFO_STATE = "FUIS"; - private static final String FETCH_SUBSCRIPTIONS_STATE = "FSS"; - private static final String DRAWER_ON_ACCOUNT_SWITCH_STATE = "DOASS"; - private static final String IS_IN_LAZY_MODE_STATE = "IILMS"; - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - private static final String ACCOUNT_NAME_STATE = "ANS"; - private static final String ACCOUNT_PROFILE_IMAGE_URL_STATE = "APIUS"; - private static final String ACCOUNT_BANNER_IMAGE_URL_STATE = "ABIUS"; - private static final String ACCOUNT_KARMA_STATE = "AKS"; - private static final String MESSAGE_FULLNAME_STATE = "MFS"; - private static final String NEW_ACCOUNT_NAME_STATE = "NANS"; - - private static final int LOGIN_ACTIVITY_REQUEST_CODE = 0; - - @BindView(R.id.drawer_layout) DrawerLayout drawer; - @BindView(R.id.coordinator_layout_main_activity) CoordinatorLayout coordinatorLayout; - @BindView(R.id.appbar_layout_main_activity) AppBarLayout appBarLayout; - @BindView(R.id.view_pager_main_activity) ViewPager viewPager; - @BindView(R.id.collapsing_toolbar_layout_main_activity) CollapsingToolbarLayout collapsingToolbarLayout; - @BindView(R.id.toolbar) Toolbar toolbar; - @BindView(R.id.nested_scroll_view_main_activity) NestedScrollView nestedScrollView; - @BindView(R.id.all_drawer_items_linear_layout_main_activity) LinearLayout allDrawerItemsLinearLayout; - @BindView(R.id.account_label_main_activity) TextView accountLabelTextView; - @BindView(R.id.profile_linear_layout_main_activity) LinearLayout profileLinearLayout; - @BindView(R.id.subscriptions_linear_layout_main_activity) LinearLayout subscriptionLinearLayout; - @BindView(R.id.inbox_linear_layout_main_activity) LinearLayout inboxLinearLayout; - @BindView(R.id.post_label_main_activity) TextView postLabelTextView; - @BindView(R.id.upvoted_linear_layout_main_activity) LinearLayout upvotedLinearLayout; - @BindView(R.id.downvoted_linear_layout_main_activity) LinearLayout downvotedLinearLayout; - @BindView(R.id.hidden_linear_layout_main_activity) LinearLayout hiddenLinearLayout; - @BindView(R.id.saved_linear_layout_main_activity) LinearLayout savedLinearLayout; - @BindView(R.id.gilded_linear_layout_main_activity) LinearLayout gildedLinearLayout; - @BindView(R.id.divider_main_activity) View divider; - @BindView(R.id.settings_linear_layout_main_activity) LinearLayout settingsLinearLayout; - @BindView(R.id.account_recycler_view_main_activity) RecyclerView accountRecyclerView; - @BindView(R.id.tab_layout_main_activity) TabLayout tabLayout; - @BindView(R.id.fab_main_activity) FloatingActionButton fab; - - private SectionsPagerAdapter sectionsPagerAdapter; - - private TextView mAccountNameTextView; - private TextView mKarmaTextView; - private GifImageView mProfileImageView; - private ImageView mBannerImageView; - private ImageView mDropIconImageView; - - private RequestManager glide; - private AppBarLayout.LayoutParams params; - private PostTypeBottomSheetFragment postTypeBottomSheetFragment; - private SortTypeBottomSheetFragment bestSortTypeBottomSheetFragment; - private SortTypeBottomSheetFragment popularAndAllSortTypeBottomSheetFragment; - - private boolean mNullAccessToken = false; - private String mAccessToken; - private String mAccountName; - private String mProfileImageUrl; - private String mBannerImageUrl; - private int mKarma; - private boolean mFetchUserInfoSuccess = false; - private boolean mFetchSubscriptionsSuccess = false; - private boolean mDrawerOnAccountSwitch = false; - private String mMessageFullname; - private String mNewAccountName; - - private Menu mMenu; - - private boolean isInLazyMode = false; - - AccountViewModel accountViewModel; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - setTheme(R.style.AppTheme_NoActionBarWithTransparentStatusBar); - - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_main); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - Resources resources = getResources(); - - if(resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { - Window window = getWindow(); - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - - boolean lightNavBar = false; - if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - lightNavBar = true; - } - boolean finalLightNavBar = lightNavBar; - - View decorView = window.getDecorView(); - appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { - @Override - void onStateChanged(AppBarLayout appBarLayout, State state) { - if(state == State.COLLAPSED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } else if(state == State.EXPANDED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } - } - }); - - int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); - if (statusBarResourceId > 0) { - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); - params.topMargin = resources.getDimensionPixelSize(statusBarResourceId); - toolbar.setLayoutParams(params); - } - - int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); - if (navBarResourceId > 0) { - int navBarHeight = resources.getDimensionPixelSize(navBarResourceId); - CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) fab.getLayoutParams(); - params.bottomMargin = navBarHeight; - fab.setLayoutParams(params); - - nestedScrollView.setPadding(0, 0, 0, navBarHeight); - } - } - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - postTypeBottomSheetFragment = new PostTypeBottomSheetFragment(); - - bestSortTypeBottomSheetFragment = new SortTypeBottomSheetFragment(); - Bundle bestBundle = new Bundle(); - bestBundle.putBoolean(SortTypeBottomSheetFragment.EXTRA_NO_BEST_TYPE, false); - bestSortTypeBottomSheetFragment.setArguments(bestBundle); - - popularAndAllSortTypeBottomSheetFragment = new SortTypeBottomSheetFragment(); - Bundle popularBundle = new Bundle(); - popularBundle.putBoolean(SortTypeBottomSheetFragment.EXTRA_NO_BEST_TYPE, true); - popularAndAllSortTypeBottomSheetFragment.setArguments(popularBundle); - - setSupportActionBar(toolbar); - - drawer = findViewById(R.id.drawer_layout); - ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( - this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); - drawer.addDrawerListener(toggle); - toggle.syncState(); - - params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); - - if(savedInstanceState != null) { - mFetchUserInfoSuccess = savedInstanceState.getBoolean(FETCH_USER_INFO_STATE); - mFetchSubscriptionsSuccess = savedInstanceState.getBoolean(FETCH_SUBSCRIPTIONS_STATE); - mDrawerOnAccountSwitch = savedInstanceState.getBoolean(DRAWER_ON_ACCOUNT_SWITCH_STATE); - isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); - mProfileImageUrl = savedInstanceState.getString(ACCOUNT_PROFILE_IMAGE_URL_STATE); - mBannerImageUrl = savedInstanceState.getString(ACCOUNT_BANNER_IMAGE_URL_STATE); - mKarma = savedInstanceState.getInt(ACCOUNT_KARMA_STATE); - mMessageFullname = savedInstanceState.getString(MESSAGE_FULLNAME_STATE); - mNewAccountName = savedInstanceState.getString(NEW_ACCOUNT_NAME_STATE); - - if(!mNullAccessToken && mAccessToken == null) { - getCurrentAccountAndBindView(); - } else { - bindView(); - } - } else { - mMessageFullname = getIntent().getStringExtra(EXTRA_MESSSAGE_FULLNAME); - mNewAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); - getCurrentAccountAndBindView(); - } - - fab.setOnClickListener(view -> { - if(mAccessToken == null) { - Toast.makeText(MainActivity.this, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - postTypeBottomSheetFragment.show(getSupportFragmentManager(), postTypeBottomSheetFragment.getTag()); - }); - } - - private void getCurrentAccountAndBindView() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - boolean enableNotification = mSharedPreferences.getBoolean(SharedPreferencesUtils.ENABLE_NOTIFICATION_KEY, true); - String notificationInterval = mSharedPreferences.getString(SharedPreferencesUtils.NOTIFICATION_INTERVAL_KEY, "1"); - - WorkManager workManager = WorkManager.getInstance(this); - - if(mNewAccountName != null) { - if(account == null || !account.getUsername().equals(mNewAccountName)) { - new SwitchAccountAsyncTask(mRedditDataRoomDatabase, mNewAccountName, newAccount -> { - EventBus.getDefault().post(new SwitchAccountEvent(getClass().getName())); - Toast.makeText(this, R.string.account_switched, Toast.LENGTH_SHORT).show(); - - mNewAccountName = null; - if(newAccount == null) { - mNullAccessToken = true; - - if(mMenu != null) { - mMenu.findItem(R.id.action_subscriptions_main_activity).setVisible(false); - } - } else { - mAccessToken = newAccount.getAccessToken(); - mAccountName = newAccount.getUsername(); - mProfileImageUrl = newAccount.getProfileImageUrl(); - mBannerImageUrl = newAccount.getBannerImageUrl(); - mKarma = newAccount.getKarma(); - - if(mMenu != null) { - mMenu.findItem(R.id.action_subscriptions_main_activity).setVisible(true); - } - } - - if(enableNotification) { - Constraints constraints = new Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build(); - - PeriodicWorkRequest pullNotificationRequest = - new PeriodicWorkRequest.Builder(PullNotificationWorker.class, - Long.parseLong(notificationInterval), TimeUnit.HOURS) - .setConstraints(constraints) - .build(); - - workManager.enqueueUniquePeriodicWork(PullNotificationWorker.WORKER_TAG, - ExistingPeriodicWorkPolicy.KEEP, pullNotificationRequest); - } else { - workManager.cancelUniqueWork(PullNotificationWorker.WORKER_TAG); - } - - bindView(); - }).execute(); - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - mProfileImageUrl = account.getProfileImageUrl(); - mBannerImageUrl = account.getBannerImageUrl(); - mKarma = account.getKarma(); - - if(mMenu != null) { - mMenu.findItem(R.id.action_subscriptions_main_activity).setVisible(true); - } - - if(enableNotification) { - Constraints constraints = new Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build(); - - PeriodicWorkRequest pullNotificationRequest = - new PeriodicWorkRequest.Builder(PullNotificationWorker.class, - Long.parseLong(notificationInterval), TimeUnit.HOURS) - .setConstraints(constraints) - .build(); - - workManager.enqueueUniquePeriodicWork(PullNotificationWorker.WORKER_TAG, - ExistingPeriodicWorkPolicy.KEEP, pullNotificationRequest); - } else { - workManager.cancelUniqueWork(PullNotificationWorker.WORKER_TAG); - } - - bindView(); - } - } else { - if(account == null) { - mNullAccessToken = true; - - if(mMenu != null) { - mMenu.findItem(R.id.action_subscriptions_main_activity).setVisible(false); - } - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - mProfileImageUrl = account.getProfileImageUrl(); - mBannerImageUrl = account.getBannerImageUrl(); - mKarma = account.getKarma(); - - if(mMenu != null) { - mMenu.findItem(R.id.action_subscriptions_main_activity).setVisible(true); - } - } - - if(enableNotification) { - Constraints constraints = new Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build(); - - PeriodicWorkRequest pullNotificationRequest = - new PeriodicWorkRequest.Builder(PullNotificationWorker.class, - Long.parseLong(notificationInterval), TimeUnit.HOURS) - .setConstraints(constraints) - .build(); - - workManager.enqueueUniquePeriodicWork(PullNotificationWorker.WORKER_TAG, - ExistingPeriodicWorkPolicy.KEEP, pullNotificationRequest); - } else { - workManager.cancelUniqueWork(PullNotificationWorker.WORKER_TAG); - } - - bindView(); - } - }).execute(); - } - - private void bindView() { - if(isDestroyed()) { - return; - } - - sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); - viewPager.setAdapter(sectionsPagerAdapter); - viewPager.setOffscreenPageLimit(3); - tabLayout.setupWithViewPager(viewPager); - - viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {} - - @Override - public void onPageSelected(int position) { - fab.show(); - if(isInLazyMode) { - if(position == sectionsPagerAdapter.getCurrentLazyModeFragmentPosition()) { - sectionsPagerAdapter.resumeLazyMode(); - } else { - sectionsPagerAdapter.pauseLazyMode(); - } - } - } - - @Override - public void onPageScrollStateChanged(int state) {} - }); - - loadSubscriptions(); - - glide = Glide.with(this); - - AccountRecyclerViewAdapter adapter = new AccountRecyclerViewAdapter(this, glide, mAccountName, - new AccountRecyclerViewAdapter.ItemSelectedListener() { - @Override - public void accountSelected(Account account) { - new SwitchAccountAsyncTask(mRedditDataRoomDatabase, account.getUsername(), newAccount -> { - Intent intent = new Intent(MainActivity.this, MainActivity.class); - startActivity(intent); - finish(); - }).execute(); - } - - @Override - public void addAccountSelected() { - Intent intent = new Intent(MainActivity.this, LoginActivity.class); - startActivityForResult(intent, LOGIN_ACTIVITY_REQUEST_CODE); - } - - @Override - public void anonymousSelected() { - new SwitchToAnonymousAccountAsyncTask(mRedditDataRoomDatabase, false, - () -> { - Intent intent = new Intent(MainActivity.this, MainActivity.class); - startActivity(intent); - finish(); - }).execute(); - } - - @Override - public void logoutSelected() { - new SwitchToAnonymousAccountAsyncTask(mRedditDataRoomDatabase, true, - () -> { - Intent intent = new Intent(MainActivity.this, MainActivity.class); - startActivity(intent); - finish(); - }).execute(); - } - }); - - accountRecyclerView.setLayoutManager(new LinearLayoutManager(this)); - accountRecyclerView.setNestedScrollingEnabled(false); - accountRecyclerView.setAdapter(adapter); - - accountViewModel = new ViewModelProvider(this, - new AccountViewModel.Factory(getApplication(), mRedditDataRoomDatabase, mAccountName)).get(AccountViewModel.class); - accountViewModel.getAccountsExceptCurrentAccountLiveData().observe(this, adapter::changeAccountsDataset); - - if(getIntent().hasExtra(EXTRA_POST_TYPE)) { - String type = getIntent().getStringExtra(EXTRA_POST_TYPE); - if(type != null && type.equals("popular")) { - viewPager.setCurrentItem(1); - } else { - viewPager.setCurrentItem(2); - } - } - - View header = findViewById(R.id.nav_header_main_activity); - mAccountNameTextView = header.findViewById(R.id.name_text_view_nav_header_main); - mKarmaTextView = header.findViewById(R.id.karma_text_view_nav_header_main); - mProfileImageView = header.findViewById(R.id.profile_image_view_nav_header_main); - mBannerImageView = header.findViewById(R.id.banner_image_view_nav_header_main); - mDropIconImageView = header.findViewById(R.id.account_switcher_image_view_nav_header_main); - - if(mDrawerOnAccountSwitch) { - mDropIconImageView.setImageDrawable(getResources().getDrawable(R.drawable.ic_baseline_arrow_drop_up_24px)); - accountRecyclerView.setVisibility(View.VISIBLE); - allDrawerItemsLinearLayout.setVisibility(View.GONE); - } else { - mDropIconImageView.setImageDrawable(getResources().getDrawable(R.drawable.ic_baseline_arrow_drop_down_24px)); - accountRecyclerView.setVisibility(View.GONE); - allDrawerItemsLinearLayout.setVisibility(View.VISIBLE); - } - - header.setOnClickListener(view -> { - if(mDrawerOnAccountSwitch) { - mDrawerOnAccountSwitch = false; - mDropIconImageView.setImageDrawable(getResources().getDrawable(R.drawable.ic_baseline_arrow_drop_down_24px)); - accountRecyclerView.setVisibility(View.GONE); - allDrawerItemsLinearLayout.setVisibility(View.VISIBLE); - } else { - mDrawerOnAccountSwitch = true; - mDropIconImageView.setImageDrawable(getResources().getDrawable(R.drawable.ic_baseline_arrow_drop_up_24px)); - accountRecyclerView.setVisibility(View.VISIBLE); - allDrawerItemsLinearLayout.setVisibility(View.GONE); - } - }); - - loadUserData(); - - if(mAccessToken != null) { - mKarmaTextView.setText(getString(R.string.karma_info, mKarma)); - mAccountNameTextView.setText(mAccountName); - if(mMessageFullname != null) { - ReadMessage.readMessage(mOauthRetrofit, mAccessToken, mMessageFullname, new ReadMessage.ReadMessageListener() { - @Override - public void readSuccess() { - mMessageFullname = null; - } - - @Override - public void readFailed() { - - } - }); - } - } else { - mKarmaTextView.setText(R.string.press_here_to_login); - mAccountNameTextView.setText(R.string.anonymous_account); - accountLabelTextView.setVisibility(View.GONE); - profileLinearLayout.setVisibility(View.GONE); - subscriptionLinearLayout.setVisibility(View.GONE); - inboxLinearLayout.setVisibility(View.GONE); - postLabelTextView.setVisibility(View.GONE); - upvotedLinearLayout.setVisibility(View.GONE); - downvotedLinearLayout.setVisibility(View.GONE); - hiddenLinearLayout.setVisibility(View.GONE); - savedLinearLayout.setVisibility(View.GONE); - gildedLinearLayout.setVisibility(View.GONE); - divider.setVisibility(View.GONE); - } - - if (mProfileImageUrl != null && !mProfileImageUrl.equals("")) { - glide.load(mProfileImageUrl) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(144, 0))) - .error(glide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(144, 0)))) - .into(mProfileImageView); - } else { - glide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(144, 0))) - .into(mProfileImageView); - } - - if (mBannerImageUrl != null && !mBannerImageUrl.equals("")) { - glide.load(mBannerImageUrl).into(mBannerImageView); - } - - profileLinearLayout.setOnClickListener(view -> { - Intent intent = new Intent(this, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mAccountName); - startActivity(intent); - drawer.closeDrawers(); - }); - - subscriptionLinearLayout.setOnClickListener(view -> { - Intent intent = new Intent(this, SubscribedThingListingActivity.class); - startActivity(intent); - drawer.closeDrawers(); - }); - - inboxLinearLayout.setOnClickListener(view -> { - Intent intent = new Intent(this, ViewMessageActivity.class); - startActivity(intent); - drawer.closeDrawers(); - }); - - upvotedLinearLayout.setOnClickListener(view -> { - Intent intent = new Intent(MainActivity.this, AccountPostsActivity.class); - intent.putExtra(AccountPostsActivity.EXTRA_USER_WHERE, PostDataSource.USER_WHERE_UPVOTED); - startActivity(intent); - drawer.closeDrawers(); - }); - - downvotedLinearLayout.setOnClickListener(view -> { - Intent intent = new Intent(MainActivity.this, AccountPostsActivity.class); - intent.putExtra(AccountPostsActivity.EXTRA_USER_WHERE, PostDataSource.USER_WHERE_DOWNVOTED); - startActivity(intent); - drawer.closeDrawers(); - }); - - hiddenLinearLayout.setOnClickListener(view -> { - Intent intent = new Intent(MainActivity.this, AccountPostsActivity.class); - intent.putExtra(AccountPostsActivity.EXTRA_USER_WHERE, PostDataSource.USER_WHERE_HIDDEN); - startActivity(intent); - drawer.closeDrawers(); - }); - - savedLinearLayout.setOnClickListener(view -> { - Intent intent = new Intent(MainActivity.this, AccountSavedThingActivity.class); - startActivity(intent); - drawer.closeDrawers(); - }); - - gildedLinearLayout.setOnClickListener(view -> { - Intent intent = new Intent(MainActivity.this, AccountPostsActivity.class); - intent.putExtra(AccountPostsActivity.EXTRA_USER_WHERE, PostDataSource.USER_WHERE_GILDED); - startActivity(intent); - drawer.closeDrawers(); - }); - - settingsLinearLayout.setOnClickListener(view -> { - drawer.closeDrawers(); - Intent intent = new Intent(MainActivity.this, SettingsActivity.class); - startActivity(intent); - }); - } - - private void loadSubscriptions() { - if (mAccessToken != null && !mFetchSubscriptionsSuccess) { - FetchSubscribedThing.fetchSubscribedThing(mOauthRetrofit, mAccessToken, mAccountName, null, - new ArrayList<>(), new ArrayList<>(), - new ArrayList<>(), - new FetchSubscribedThing.FetchSubscribedThingListener() { - @Override - public void onFetchSubscribedThingSuccess(ArrayList subscribedSubredditData, - ArrayList subscribedUserData, - ArrayList subredditData) { - new InsertSubscribedThingsAsyncTask( - mRedditDataRoomDatabase, - mAccountName, - subscribedSubredditData, - subscribedUserData, - subredditData, - () -> mFetchSubscriptionsSuccess = true).execute(); - } - - @Override - public void onFetchSubscribedThingFail() { - mFetchSubscriptionsSuccess = false; - } - }); - } - } - - private void loadUserData() { - if (!mFetchUserInfoSuccess) { - FetchMyInfo.fetchAccountInfo(mOauthRetrofit, mAccessToken, new FetchMyInfo.FetchUserMyListener() { - @Override - public void onFetchMyInfoSuccess(String response) { - ParseAndSaveAccountInfo.parseAndSaveAccountInfo(response, mRedditDataRoomDatabase, new ParseAndSaveAccountInfo.ParseAndSaveAccountInfoListener() { - @Override - public void onParseMyInfoSuccess(String name, String profileImageUrl, String bannerImageUrl, int karma) { - mAccountNameTextView.setText(name); - if (profileImageUrl != null && !profileImageUrl.equals("")) { - glide.load(profileImageUrl) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0))) - .error(glide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0)))) - .into(mProfileImageView); - } else { - glide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(128, 0))) - .into(mProfileImageView); - } - if (bannerImageUrl != null && !bannerImageUrl.equals("")) { - glide.load(bannerImageUrl).into(mBannerImageView); - } - - mAccountName = name; - mProfileImageUrl = profileImageUrl; - mBannerImageUrl = bannerImageUrl; - mKarma = karma; - - mKarmaTextView.setText(getString(R.string.karma_info, karma)); - - mFetchUserInfoSuccess = true; - } - - @Override - public void onParseMyInfoFail() { - mFetchUserInfoSuccess = false; - } - }); - } - - @Override - public void onFetchMyInfoFail() { - mFetchUserInfoSuccess = false; - } - }); - } - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if(requestCode == LOGIN_ACTIVITY_REQUEST_CODE && resultCode == Activity.RESULT_OK) { - Intent intent = new Intent(this, MainActivity.class); - startActivity(intent); - finish(); - } - - super.onActivityResult(requestCode, resultCode, data); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.main_activity, menu); - mMenu = menu; - MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_main_activity); - MenuItem subscriptionsItem = mMenu.findItem(R.id.action_subscriptions_main_activity); - - if(mAccessToken != null) { - subscriptionsItem.setVisible(true); - } else { - subscriptionsItem.setVisible(false); - } - - if(isInLazyMode) { - lazyModeItem.setTitle(R.string.action_stop_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); - collapsingToolbarLayout.setLayoutParams(params); - } else { - lazyModeItem.setTitle(R.string.action_start_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); - collapsingToolbarLayout.setLayoutParams(params); - } - - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case R.id.action_subscriptions_main_activity: - Intent subscriptionsIntent = new Intent(this, SubscribedThingListingActivity.class); - startActivity(subscriptionsIntent); - return true; - case R.id.action_sort_main_activity: - if(viewPager.getCurrentItem() == 1 ||viewPager.getCurrentItem() == 2) { - popularAndAllSortTypeBottomSheetFragment.show(getSupportFragmentManager(), popularAndAllSortTypeBottomSheetFragment.getTag()); - } else { - bestSortTypeBottomSheetFragment.show(getSupportFragmentManager(), bestSortTypeBottomSheetFragment.getTag()); - } - return true; - case R.id.action_search_main_activity: - Intent intent = new Intent(this, SearchActivity.class); - intent.putExtra(SearchActivity.EXTRA_SEARCH_ONLY_SUBREDDITS, false); - startActivity(intent); - return true; - case R.id.action_refresh_main_activity: - if(mMenu != null) { - mMenu.findItem(R.id.action_lazy_mode_main_activity).setTitle(R.string.action_start_lazy_mode); - } - sectionsPagerAdapter.refresh(); - mFetchUserInfoSuccess = false; - loadUserData(); - return true; - case R.id.action_lazy_mode_main_activity: - MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_main_activity); - if(isInLazyMode) { - sectionsPagerAdapter.stopLazyMode(); - isInLazyMode = false; - lazyModeItem.setTitle(R.string.action_start_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); - collapsingToolbarLayout.setLayoutParams(params); - } else { - if(sectionsPagerAdapter.startLazyMode()) { - isInLazyMode = true; - lazyModeItem.setTitle(R.string.action_stop_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); - collapsingToolbarLayout.setLayoutParams(params); - } - } - return true; - } - return false; - } - - @Override - public void onBackPressed() { - DrawerLayout drawer = findViewById(R.id.drawer_layout); - if (drawer.isDrawerOpen(GravityCompat.START)) { - drawer.closeDrawer(GravityCompat.START); - } else { - super.onBackPressed(); - } - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean(FETCH_USER_INFO_STATE, mFetchUserInfoSuccess); - outState.putBoolean(FETCH_SUBSCRIPTIONS_STATE, mFetchSubscriptionsSuccess); - outState.putBoolean(DRAWER_ON_ACCOUNT_SWITCH_STATE, mDrawerOnAccountSwitch); - outState.putBoolean(IS_IN_LAZY_MODE_STATE, isInLazyMode); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - outState.putString(ACCOUNT_NAME_STATE, mAccountName); - outState.putString(ACCOUNT_PROFILE_IMAGE_URL_STATE, mProfileImageUrl); - outState.putString(ACCOUNT_BANNER_IMAGE_URL_STATE, mBannerImageUrl); - outState.putInt(ACCOUNT_KARMA_STATE, mKarma); - outState.putString(MESSAGE_FULLNAME_STATE, mMessageFullname); - outState.putString(NEW_ACCOUNT_NAME_STATE, mNewAccountName); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - @Override - public void sortTypeSelected(String sortType) { - sectionsPagerAdapter.changeSortType(sortType); - } - - @Override - public void postTypeSelected(int postType) { - Intent intent; - switch (postType) { - case PostTypeBottomSheetFragment.TYPE_TEXT: - intent = new Intent(MainActivity.this, PostTextActivity.class); - startActivity(intent); - break; - case PostTypeBottomSheetFragment.TYPE_LINK: - intent = new Intent(MainActivity.this, PostLinkActivity.class); - startActivity(intent); - break; - case PostTypeBottomSheetFragment.TYPE_IMAGE: - intent = new Intent(MainActivity.this, PostImageActivity.class); - startActivity(intent); - break; - case PostTypeBottomSheetFragment.TYPE_VIDEO: - intent = new Intent(MainActivity.this, PostVideoActivity.class); - startActivity(intent); - } - } - - public void postScrollUp() { - fab.show(); - } - - public void postScrollDown() { - fab.hide(); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - if(!getClass().getName().equals(event.excludeActivityClassName)) { - finish(); - } - } - - @Subscribe - public void onChangeNSFWEvent(ChangeNSFWEvent changeNSFWEvent) { - sectionsPagerAdapter.changeNSFW(changeNSFWEvent.nsfw); - } - - @Subscribe - public void onChangeFontSizeEvent(ChangeFontSizeEvent changeFontSizeEvent) { - recreate(); - } - - private class SectionsPagerAdapter extends FragmentPagerAdapter { - private PostFragment frontPagePostFragment; - private PostFragment popularPostFragment; - private PostFragment allPostFragment; - - SectionsPagerAdapter(FragmentManager fm) { - super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); - } - - @NonNull - @Override - public Fragment getItem(int position) { - if(mAccessToken == null) { - if(position == 0) { - PostFragment fragment = new PostFragment(); - Bundle bundle = new Bundle(); - bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); - bundle.putString(PostFragment.EXTRA_NAME, "popular"); - bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_HOT); - bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); - bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - fragment.setArguments(bundle); - return fragment; - } else { - PostFragment fragment = new PostFragment(); - Bundle bundle = new Bundle(); - bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); - bundle.putString(PostFragment.EXTRA_NAME, "all"); - bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_HOT); - bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); - bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - fragment.setArguments(bundle); - return fragment; - } - } - - if (position == 0) { - PostFragment fragment = new PostFragment(); - Bundle bundle = new Bundle(); - bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_FRONT_PAGE); - bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_BEST); - bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); - bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - fragment.setArguments(bundle); - return fragment; - } else if(position == 1) { - PostFragment fragment = new PostFragment(); - Bundle bundle = new Bundle(); - bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); - bundle.putString(PostFragment.EXTRA_NAME, "popular"); - bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_HOT); - bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); - bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - fragment.setArguments(bundle); - return fragment; - } else { - PostFragment fragment = new PostFragment(); - Bundle bundle = new Bundle(); - bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); - bundle.putString(PostFragment.EXTRA_NAME, "all"); - bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_HOT); - bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); - bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - fragment.setArguments(bundle); - return fragment; - } - } - - @Override - public int getCount() - { - if(mAccessToken == null) { - return 2; - } - return 3; - } - - @Override - public CharSequence getPageTitle(int position) { - if(mAccessToken == null) { - switch (position) { - case 0: - return "Popular"; - case 1: - return "All"; - } - } else { - switch (position) { - case 0: - return "Best"; - case 1: - return "Popular"; - case 2: - return "All"; - } - } - return null; - } - - @NonNull - @Override - public Object instantiateItem(@NonNull ViewGroup container, int position) { - Fragment fragment = (Fragment) super.instantiateItem(container, position); - if(mAccessToken == null) { - switch (position) { - case 0: - popularPostFragment = (PostFragment) fragment; - break; - case 1: - allPostFragment = (PostFragment) fragment; - } - } else { - switch (position) { - case 0: - frontPagePostFragment = (PostFragment) fragment; - break; - case 1: - popularPostFragment = (PostFragment) fragment; - break; - case 2: - allPostFragment = (PostFragment) fragment; - } - } - return fragment; - } - - boolean startLazyMode() { - if(mAccessToken == null) { - switch (viewPager.getCurrentItem()) { - case 0: - return ((FragmentCommunicator) popularPostFragment).startLazyMode(); - case 1: - return ((FragmentCommunicator) allPostFragment).startLazyMode(); - } - } else { - switch (viewPager.getCurrentItem()) { - case 0: - return ((FragmentCommunicator) frontPagePostFragment).startLazyMode(); - case 1: - return ((FragmentCommunicator) popularPostFragment).startLazyMode(); - case 2: - return ((FragmentCommunicator) allPostFragment).startLazyMode(); - } - } - - return false; - } - - void stopLazyMode() { - if(mAccessToken == null) { - switch (getCurrentLazyModeFragmentPosition()) { - case 0: - ((FragmentCommunicator) popularPostFragment).stopLazyMode(); - break; - case 1: - ((FragmentCommunicator) allPostFragment).stopLazyMode(); - break; - } - } else { - switch (getCurrentLazyModeFragmentPosition()) { - case 0: - ((FragmentCommunicator) frontPagePostFragment).stopLazyMode(); - break; - case 1: - ((FragmentCommunicator) popularPostFragment).stopLazyMode(); - break; - case 2: - ((FragmentCommunicator) allPostFragment).stopLazyMode(); - break; - } - } - } - - void resumeLazyMode() { - if(mAccessToken == null) { - switch (getCurrentLazyModeFragmentPosition()) { - case 0: - ((FragmentCommunicator) popularPostFragment).resumeLazyMode(false); - break; - case 1: - ((FragmentCommunicator) allPostFragment).resumeLazyMode(false); - break; - } - } else { - switch (getCurrentLazyModeFragmentPosition()) { - case 0: - ((FragmentCommunicator) frontPagePostFragment).resumeLazyMode(false); - break; - case 1: - ((FragmentCommunicator) popularPostFragment).resumeLazyMode(false); - break; - case 2: - ((FragmentCommunicator) allPostFragment).resumeLazyMode(false); - break; - } - } - } - - void pauseLazyMode() { - if(mAccessToken == null) { - switch (getCurrentLazyModeFragmentPosition()) { - case 0: - ((FragmentCommunicator) popularPostFragment).pauseLazyMode(false); - break; - case 1: - ((FragmentCommunicator) allPostFragment).pauseLazyMode(false); - } - } else { - switch (getCurrentLazyModeFragmentPosition()) { - case 0: - ((FragmentCommunicator) frontPagePostFragment).pauseLazyMode(false); - break; - case 1: - ((FragmentCommunicator) popularPostFragment).pauseLazyMode(false); - break; - case 2: - ((FragmentCommunicator) allPostFragment).pauseLazyMode(false); - } - } - } - - int getCurrentLazyModeFragmentPosition() { - if(mAccessToken == null) { - if(!isInLazyMode) { - return -1; - } else if(popularPostFragment != null && ((FragmentCommunicator) popularPostFragment).isInLazyMode()) { - return 0; - } else if(allPostFragment != null && ((FragmentCommunicator) allPostFragment).isInLazyMode()) { - return 1; - } else { - return -1; - } - } else { - if(!isInLazyMode) { - return -1; - } else if(frontPagePostFragment != null && ((FragmentCommunicator) frontPagePostFragment).isInLazyMode()) { - return 0; - } else if(popularPostFragment != null && ((FragmentCommunicator) popularPostFragment).isInLazyMode()) { - return 1; - } else if(allPostFragment != null && ((FragmentCommunicator) allPostFragment).isInLazyMode()) { - return 2; - } else { - return -1; - } - } - } - - void changeSortType(String sortType) { - if(mAccessToken == null) { - if(viewPager.getCurrentItem() == 0) { - popularPostFragment.changeSortType(sortType); - } else { - allPostFragment.changeSortType(sortType); - } - } else { - switch (viewPager.getCurrentItem()) { - case 0: - frontPagePostFragment.changeSortType(sortType); - break; - case 1: - popularPostFragment.changeSortType(sortType); - break; - case 2: - allPostFragment.changeSortType(sortType); - } - } - } - - public void refresh() { - if(mAccessToken == null) { - if(viewPager.getCurrentItem() == 0) { - if(popularPostFragment != null) { - ((FragmentCommunicator) popularPostFragment).refresh(); - } - } else { - if(allPostFragment != null) { - ((FragmentCommunicator) allPostFragment).refresh(); - } - } - } else { - switch (viewPager.getCurrentItem()) { - case 0: - if(frontPagePostFragment != null) { - ((FragmentCommunicator) frontPagePostFragment).refresh(); - } - break; - case 1: - if(popularPostFragment != null) { - ((FragmentCommunicator) popularPostFragment).refresh(); - } - break; - case 2: - if(allPostFragment != null) { - ((FragmentCommunicator) allPostFragment).refresh(); - } - } - } - } - - void changeNSFW(boolean nsfw) { - if(frontPagePostFragment != null) { - frontPagePostFragment.changeNSFW(nsfw); - } - if(popularPostFragment != null) { - popularPostFragment.changeNSFW(nsfw); - } - if(allPostFragment != null) { - allPostFragment.changeNSFW(nsfw); - } - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Message.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Message.java index 8f4b7ae5..1ba1aea9 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Message.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Message.java @@ -1,6 +1,6 @@ package ml.docilealligator.infinityforreddit; -class Message { +public class Message { static final String TYPE_COMMENT = "t1"; static final String TYPE_ACCOUNT = "t2"; static final String TYPE_LINK = "t3"; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MessageRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MessageRecyclerViewAdapter.java deleted file mode 100644 index 6427d22b..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/MessageRecyclerViewAdapter.java +++ /dev/null @@ -1,244 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.net.Uri; -import android.text.util.Linkify; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.paging.PagedListAdapter; -import androidx.recyclerview.widget.DiffUtil; -import androidx.recyclerview.widget.RecyclerView; - -import butterknife.BindView; -import butterknife.ButterKnife; -import io.noties.markwon.AbstractMarkwonPlugin; -import io.noties.markwon.Markwon; -import io.noties.markwon.MarkwonConfiguration; -import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.linkify.LinkifyPlugin; -import retrofit2.Retrofit; - -class MessageRecyclerViewAdapter extends PagedListAdapter { - private static final int VIEW_TYPE_DATA = 0; - private static final int VIEW_TYPE_ERROR = 1; - private static final int VIEW_TYPE_LOADING = 2; - - private Context mContext; - private Retrofit mOauthRetrofit; - private Markwon mMarkwon; - private String mAccessToken; - private Resources mResources; - - private NetworkState networkState; - private RetryLoadingMoreCallback mRetryLoadingMoreCallback; - - interface RetryLoadingMoreCallback { - void retryLoadingMore(); - } - - MessageRecyclerViewAdapter(Context context, Retrofit oauthRetrofit, String accessToken, - RetryLoadingMoreCallback retryLoadingMoreCallback) { - super(DIFF_CALLBACK); - mContext = context; - mOauthRetrofit = oauthRetrofit; - mRetryLoadingMoreCallback = retryLoadingMoreCallback; - mMarkwon = Markwon.builder(mContext) - .usePlugin(new AbstractMarkwonPlugin() { - @Override - public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { - builder.linkResolver((view, link) -> { - Intent intent = new Intent(mContext, LinkResolverActivity.class); - Uri uri = Uri.parse(link); - if(uri.getScheme() == null && uri.getHost() == null) { - intent.setData(LinkResolverActivity.getRedditUriByPath(link)); - } else { - intent.setData(uri); - } - mContext.startActivity(intent); - }); - } - }) - .usePlugin(StrikethroughPlugin.create()) - .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) - .build(); - mAccessToken = accessToken; - mResources = context.getResources(); - } - - private static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() { - @Override - public boolean areItemsTheSame(@NonNull Message message, @NonNull Message t1) { - return message.getId().equals(t1.getId()); - } - - @Override - public boolean areContentsTheSame(@NonNull Message message, @NonNull Message t1) { - return message.getBody().equals(t1.getBody()); - } - }; - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - if(viewType == VIEW_TYPE_DATA) { - return new DataViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message, parent, false)); - } else if(viewType == VIEW_TYPE_ERROR) { - return new ErrorViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_error, parent, false)); - } else { - return new LoadingViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_loading, parent, false)); - } - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - if(holder instanceof DataViewHolder) { - Message message = getItem(holder.getAdapterPosition()); - if(message != null) { - if(message.isNew()) { - ((DataViewHolder) holder).itemView.setBackgroundColor( - mResources.getColor(R.color.unreadMessageBackgroundColor)); - } - - if(message.wasComment()) { - ((DataViewHolder) holder).authorTextView.setTextColor(mResources.getColor(R.color.colorPrimaryDarkDayNightTheme)); - ((DataViewHolder) holder).titleTextView.setText(message.getTitle()); - } else { - ((DataViewHolder) holder).titleTextView.setVisibility(View.GONE); - } - - ((DataViewHolder) holder).authorTextView.setText(message.getAuthor()); - String subject = message.getSubject().substring(0, 1).toUpperCase() + message.getSubject().substring(1); - ((DataViewHolder) holder).subjectTextView.setText(subject); - mMarkwon.setMarkdown(((DataViewHolder) holder).contentCustomMarkwonView, message.getBody()); - - ((DataViewHolder) holder).itemView.setOnClickListener(view -> { - if(message.getContext() != null && !message.getContext().equals("")) { - Uri uri = LinkResolverActivity.getRedditUriByPath(message.getContext()); - Intent intent = new Intent(mContext, LinkResolverActivity.class); - intent.setData(uri); - mContext.startActivity(intent); - } - - if(message.isNew()) { - ((DataViewHolder) holder).itemView.setBackgroundColor(mResources.getColor(R.color.backgroundColor)); - message.setNew(false); - - ReadMessage.readMessage(mOauthRetrofit, mAccessToken, message.getFullname(), - new ReadMessage.ReadMessageListener() { - @Override - public void readSuccess() {} - - @Override - public void readFailed() { - message.setNew(true); - ((DataViewHolder) holder).itemView.setBackgroundColor(mResources.getColor(R.color.unreadMessageBackgroundColor)); - } - }); - } - }); - - ((DataViewHolder) holder).authorTextView.setOnClickListener(view -> { - if(message.wasComment()) { - Intent intent = new Intent(mContext, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, message.getAuthor()); - mContext.startActivity(intent); - } - }); - - ((DataViewHolder) holder).contentCustomMarkwonView.setOnClickListener(view -> ((DataViewHolder) holder).itemView.performClick()); - } - } - } - - @Override - public int getItemViewType(int position) { - // Reached at the end - if (hasExtraRow() && position == getItemCount() - 1) { - if (networkState.getStatus() == NetworkState.Status.LOADING) { - return VIEW_TYPE_LOADING; - } else { - return VIEW_TYPE_ERROR; - } - } else { - return VIEW_TYPE_DATA; - } - } - - @Override - public int getItemCount() { - if(hasExtraRow()) { - return super.getItemCount() + 1; - } - return super.getItemCount(); - } - - @Override - public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { - super.onViewRecycled(holder); - if(holder instanceof DataViewHolder) { - ((DataViewHolder) holder).itemView.setBackgroundColor(mResources.getColor(R.color.backgroundColor)); - ((DataViewHolder) holder).titleTextView.setVisibility(View.VISIBLE); - ((DataViewHolder) holder).authorTextView.setTextColor(mResources.getColor(R.color.primaryTextColor)); - } - } - - private boolean hasExtraRow() { - return networkState != null && networkState.getStatus() != NetworkState.Status.SUCCESS; - } - - void setNetworkState(NetworkState newNetworkState) { - NetworkState previousState = this.networkState; - boolean previousExtraRow = hasExtraRow(); - this.networkState = newNetworkState; - boolean newExtraRow = hasExtraRow(); - if (previousExtraRow != newExtraRow) { - if (previousExtraRow) { - notifyItemRemoved(super.getItemCount()); - } else { - notifyItemInserted(super.getItemCount()); - } - } else if (newExtraRow && !previousState.equals(newNetworkState)) { - notifyItemChanged(getItemCount() - 1); - } - } - - class DataViewHolder extends RecyclerView.ViewHolder { - View itemView; - @BindView(R.id.author_text_view_item_message) TextView authorTextView; - @BindView(R.id.subject_text_view_item_message) TextView subjectTextView; - @BindView(R.id.title_text_view_item_message) TextView titleTextView; - @BindView(R.id.content_custom_markwon_view_item_message) TextView contentCustomMarkwonView; - - DataViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - this.itemView = itemView; - } - } - - class ErrorViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.error_text_view_item_footer_error) TextView errorTextView; - @BindView(R.id.retry_button_item_footer_error) Button retryButton; - - ErrorViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - errorTextView.setText(R.string.load_comments_failed); - retryButton.setOnClickListener(view -> mRetryLoadingMoreCallback.retryLoadingMore()); - } - } - - class LoadingViewHolder extends RecyclerView.ViewHolder { - LoadingViewHolder(@NonNull View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MessageViewModel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MessageViewModel.java index d111c8ad..e02c4296 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/MessageViewModel.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/MessageViewModel.java @@ -46,27 +46,27 @@ public class MessageViewModel extends ViewModel { }); } - LiveData> getMessages() { + public LiveData> getMessages() { return messages; } - LiveData getPaginationNetworkState() { + public LiveData getPaginationNetworkState() { return paginationNetworkState; } - LiveData getInitialLoadingState() { + public LiveData getInitialLoadingState() { return initialLoadingState; } - LiveData hasMessage() { + public LiveData hasMessage() { return hasMessageLiveData; } - void refresh() { + public void refresh() { messageDataSourceFactory.getMessageDataSource().invalidate(); } - void retryLoadingMore() { + public void retryLoadingMore() { messageDataSourceFactory.getMessageDataSource().retryLoadingMore(); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ModifyCommentBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ModifyCommentBottomSheetFragment.java deleted file mode 100644 index 7c39a8e4..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ModifyCommentBottomSheetFragment.java +++ /dev/null @@ -1,84 +0,0 @@ -package ml.docilealligator.infinityforreddit; - - -import android.app.Activity; -import android.content.Intent; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.fragment.app.Fragment; - -import com.deishelon.roundedbottomsheet.RoundedBottomSheetDialogFragment; - -import butterknife.BindView; -import butterknife.ButterKnife; - - -/** - * A simple {@link Fragment} subclass. - */ -public class ModifyCommentBottomSheetFragment extends RoundedBottomSheetDialogFragment { - - static final String EXTRA_COMMENT_FULLNAME = "ECF"; - static final String EXTRA_COMMENT_CONTENT = "ECC"; - static final String EXTRA_ACCESS_TOKEN = "EAT"; - static final String EXTRA_POSITION = "EP"; - - public ModifyCommentBottomSheetFragment() { - // Required empty public constructor - } - - @BindView(R.id.edit_text_view_modify_comment_bottom_sheet_fragment) TextView editTextView; - @BindView(R.id.delete_text_view_modify_comment_bottom_sheet_fragment) TextView deleteTextView; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_modify_comment_bottom_sheet, container, false); - ButterKnife.bind(this, rootView); - - Activity activity = getActivity(); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O - && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - - Bundle bundle = getArguments(); - String fullName = bundle.getString(EXTRA_COMMENT_FULLNAME); - String content = bundle.getString(EXTRA_COMMENT_CONTENT); - String accessToken = bundle.getString(EXTRA_ACCESS_TOKEN); - - editTextView.setOnClickListener(view -> { - Intent intent = new Intent(activity, EditCommentActivity.class); - intent.putExtra(EditCommentActivity.EXTRA_ACCESS_TOKEN, accessToken); - intent.putExtra(EditCommentActivity.EXTRA_FULLNAME, fullName); - intent.putExtra(EditCommentActivity.EXTRA_CONTENT, content); - intent.putExtra(EditCommentActivity.EXTRA_POSITION, bundle.getInt(EXTRA_POSITION)); - if(activity instanceof ViewPostDetailActivity) { - activity.startActivityForResult(intent, ViewPostDetailActivity.EDIT_COMMENT_REQUEST_CODE); - } else { - startActivity(intent); - } - - dismiss(); - }); - - deleteTextView.setOnClickListener(view -> { - dismiss(); - if(activity instanceof ViewPostDetailActivity) { - ((ViewPostDetailActivity) activity).deleteComment(fullName, bundle.getInt(EXTRA_POSITION)); - } else if(activity instanceof ViewUserDetailActivity) { - ((ViewUserDetailActivity) activity).deleteComment(fullName); - } - }); - - return rootView; - } - -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkState.java b/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkState.java index 4e741025..0c550b7b 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkState.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkState.java @@ -1,6 +1,6 @@ package ml.docilealligator.infinityforreddit; -class NetworkState { +public class NetworkState { public enum Status{ LOADING, SUCCESS, diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseAndInsertNewAccountAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseAndInsertNewAccountAsyncTask.java deleted file mode 100644 index 48f15207..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseAndInsertNewAccountAsyncTask.java +++ /dev/null @@ -1,51 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.AsyncTask; - -import ml.docilealligator.infinityforreddit.Account.Account; -import ml.docilealligator.infinityforreddit.Account.AccountDao; - -class ParseAndInsertNewAccountAsyncTask extends AsyncTask { - - interface ParseAndInsertAccountListener { - void success(); - } - - private String username; - private String accessToken; - private String refreshToken; - private String profileImageUrl; - private String bannerImageUrl; - private int karma; - private String code; - private AccountDao accountDao; - private ParseAndInsertAccountListener parseAndInsertAccountListener; - - ParseAndInsertNewAccountAsyncTask(String username, String accessToken, String refreshToken, String profileImageUrl, String bannerImageUrl, - int karma, String code, AccountDao accountDao, - ParseAndInsertAccountListener parseAndInsertAccountListener) { - this.username = username; - this.accessToken = accessToken; - this.refreshToken = refreshToken; - this.profileImageUrl = profileImageUrl; - this.bannerImageUrl = bannerImageUrl; - this.karma = karma; - this.code = code; - this.accountDao = accountDao; - this.parseAndInsertAccountListener = parseAndInsertAccountListener; - } - - @Override - protected Void doInBackground(Void... voids) { - Account account = new Account(username, accessToken, refreshToken, code, profileImageUrl, - bannerImageUrl, karma, true); - accountDao.markAllAccountsNonCurrent(); - accountDao.insert(account); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - parseAndInsertAccountListener.success(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseAndSaveAccountInfo.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseAndSaveAccountInfo.java index 2494192b..218b7af4 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseAndSaveAccountInfo.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseAndSaveAccountInfo.java @@ -6,14 +6,14 @@ import android.text.Html; import org.json.JSONException; import org.json.JSONObject; -class ParseAndSaveAccountInfo { - interface ParseAndSaveAccountInfoListener { +public class ParseAndSaveAccountInfo { + public interface ParseAndSaveAccountInfoListener { void onParseMyInfoSuccess(String name, String profileImageUrl, String bannerImageUrl, int karma); void onParseMyInfoFail(); } - static void parseAndSaveAccountInfo(String response, RedditDataRoomDatabase redditDataRoomDatabase, - ParseAndSaveAccountInfoListener parseAndSaveAccountInfoListener) { + public static void parseAndSaveAccountInfo(String response, RedditDataRoomDatabase redditDataRoomDatabase, + ParseAndSaveAccountInfoListener parseAndSaveAccountInfoListener) { new ParseAndSaveAccountInfoAsyncTask(response, redditDataRoomDatabase, parseAndSaveAccountInfoListener).execute(); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java index 41082a8c..7881803b 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java @@ -18,8 +18,8 @@ import static ml.docilealligator.infinityforreddit.CommentData.VOTE_TYPE_DOWNVOT import static ml.docilealligator.infinityforreddit.CommentData.VOTE_TYPE_NO_VOTE; import static ml.docilealligator.infinityforreddit.CommentData.VOTE_TYPE_UPVOTE; -class ParseComment { - interface ParseCommentListener { +public class ParseComment { + public interface ParseCommentListener { void onParseCommentSuccess(ArrayList expandedComments, String parentId, ArrayList moreChildrenFullnames); void onParseCommentFailed(); @@ -30,8 +30,8 @@ class ParseComment { void onParseSentCommentFailed(@Nullable String errorMessage); } - static void parseComment(String response, ArrayList commentData, Locale locale, - ParseCommentListener parseCommentListener) { + public static void parseComment(String response, ArrayList commentData, Locale locale, + ParseCommentListener parseCommentListener) { try { JSONArray childrenArray = new JSONArray(response); String parentId = childrenArray.getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java index 69d1fa9b..ca593e0a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java @@ -12,17 +12,19 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Locale; +import ml.docilealligator.infinityforreddit.Fragment.PostFragment; + /** * Created by alex on 3/21/18. */ -class ParsePost { +public class ParsePost { interface ParsePostsListingListener { void onParsePostsListingSuccess(ArrayList newPostData, String lastItem); void onParsePostsListingFail(); } - interface ParsePostListener { + public interface ParsePostListener { void onParsePostSuccess(Post post); void onParsePostFail(); } @@ -32,7 +34,7 @@ class ParsePost { new ParsePostDataAsyncTask(response, locale, nPosts, filter, nsfw, parsePostsListingListener).execute(); } - static void parsePost(String response, Locale locale, ParsePostListener parsePostListener) { + public static void parsePost(String response, Locale locale, ParsePostListener parsePostListener) { new ParsePostDataAsyncTask(response, locale, true, parsePostListener).execute(); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Post.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Post.java index 7f1ba645..568c4779 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Post.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Post.java @@ -7,14 +7,14 @@ import android.os.Parcelable; * Created by alex on 3/1/18. */ -class Post implements Parcelable { - static final int NSFW_TYPE = -1; - static final int TEXT_TYPE = 0; - static final int IMAGE_TYPE = 1; - static final int LINK_TYPE = 2; - static final int VIDEO_TYPE = 3; - static final int GIF_VIDEO_TYPE = 4; - static final int NO_PREVIEW_LINK_TYPE = 5; +public class Post implements Parcelable { + public static final int NSFW_TYPE = -1; + public static final int TEXT_TYPE = 0; + public static final int IMAGE_TYPE = 1; + public static final int LINK_TYPE = 2; + public static final int VIDEO_TYPE = 3; + public static final int GIF_VIDEO_TYPE = 4; + public static final int NO_PREVIEW_LINK_TYPE = 5; private String id; private String fullName; @@ -49,7 +49,7 @@ class Post implements Parcelable { private boolean isCrosspost; private String crosspostParentId; - Post(String id, String fullName, String subredditName, String subredditNamePrefixed, String author, + public Post(String id, String fullName, String subredditName, String subredditNamePrefixed, String author, String postTime, String title, String previewUrl, String permalink, int score, int postType, int voteType, int gilded, int nComments, String flair, boolean hidden, boolean spoiler, boolean nsfw, boolean stickied, boolean archived, boolean locked, boolean saved, boolean isCrosspost) { @@ -79,7 +79,7 @@ class Post implements Parcelable { this.isCrosspost = isCrosspost; } - Post(String id, String fullName, String subredditName, String subredditNamePrefixed, String author, + public Post(String id, String fullName, String subredditName, String subredditNamePrefixed, String author, String postTime, String title, String previewUrl, String url, String permalink, int score, int postType, int voteType, int gilded, int nComments, String flair, boolean hidden, boolean spoiler, boolean nsfw, boolean stickied, boolean archived, boolean locked, @@ -111,7 +111,7 @@ class Post implements Parcelable { this.isCrosspost = isCrosspost; } - Post(String id, String fullName, String subredditName, String subredditNamePrefixed, String author, + public Post(String id, String fullName, String subredditName, String subredditNamePrefixed, String author, String postTime, String title, String permalink, int score, int postType, int voteType, int gilded, int nComments, String flair, boolean hidden, boolean spoiler, boolean nsfw, boolean stickied, boolean archived, boolean locked, boolean saved, boolean isCrosspost) { @@ -191,43 +191,43 @@ class Post implements Parcelable { return id; } - String getFullName() { + public String getFullName() { return fullName; } - String getSubredditName() { + public String getSubredditName() { return subredditName; } - String getSubredditNamePrefixed() { + public String getSubredditNamePrefixed() { return subredditNamePrefixed; } - String getSubredditIconUrl() { + public String getSubredditIconUrl() { return subredditIconUrl; } - void setSubredditIconUrl(String subredditIconUrl) { + public void setSubredditIconUrl(String subredditIconUrl) { this.subredditIconUrl = subredditIconUrl; } - String getAuthor() { + public String getAuthor() { return author; } - String getAuthorNamePrefixed() { + public String getAuthorNamePrefixed() { return authorNamePrefixed; } - String getAuthorIconUrl() { + public String getAuthorIconUrl() { return authorIconUrl; } - void setAuthorIconUrl(String authorIconUrl) { + public void setAuthorIconUrl(String authorIconUrl) { this.authorIconUrl = authorIconUrl; } - String getPostTime() { + public String getPostTime() { return postTime; } @@ -239,31 +239,31 @@ class Post implements Parcelable { return title; } - void setSelfText(String selfText) { + public void setSelfText(String selfText) { this.selfText = selfText; } - String getSelfText() { + public String getSelfText() { return selfText; } - String getPreviewUrl() { + public String getPreviewUrl() { return previewUrl; } - String getUrl() { + public String getUrl() { return url; } - void setVideoUrl(String videoUrl) { + public void setVideoUrl(String videoUrl) { this.videoUrl = videoUrl; } - String getVideoUrl() { + public String getVideoUrl() { return videoUrl; } - String getPermalink() { + public String getPermalink() { return permalink; } @@ -271,47 +271,47 @@ class Post implements Parcelable { return flair; } - void setFlair(String flair) { + public void setFlair(String flair) { this.flair = flair; } - void setScore(int score) { + public void setScore(int score) { this.score = score; } - int getScore() { + public int getScore() { return score; } - int getPostType() { + public int getPostType() { return postType; } - void setVoteType(int voteType) { + public void setVoteType(int voteType) { this.voteType = voteType; } - int getVoteType() { + public int getVoteType() { return voteType; } - int getGilded() { + public int getGilded() { return gilded; } - void setPreviewWidth(int previewWidth) { + public void setPreviewWidth(int previewWidth) { this.previewWidth = previewWidth; } - int getPreviewWidth() { + public int getPreviewWidth() { return previewWidth; } - void setPreviewHeight(int previewHeight) { + public void setPreviewHeight(int previewHeight) { this.previewHeight = previewHeight; } - int getPreviewHeight() { + public int getPreviewHeight() { return previewHeight; } @@ -323,27 +323,27 @@ class Post implements Parcelable { this.nComments = nComments; } - boolean isHidden() { + public boolean isHidden() { return hidden; } - void setHidden(boolean hidden) { + public void setHidden(boolean hidden) { this.hidden = hidden; } - boolean isSpoiler() { + public boolean isSpoiler() { return spoiler; } - void setSpoiler(boolean spoiler) { + public void setSpoiler(boolean spoiler) { this.spoiler = spoiler; } - boolean isNSFW() { + public boolean isNSFW() { return nsfw; } - void setNSFW(boolean nsfw) { + public void setNSFW(boolean nsfw) { this.nsfw = nsfw; } @@ -352,27 +352,27 @@ class Post implements Parcelable { return 0; } - boolean isStickied() { + public boolean isStickied() { return stickied; } - boolean isArchived() { + public boolean isArchived() { return archived; } - boolean isLocked() { + public boolean isLocked() { return locked; } - boolean isSaved() { + public boolean isSaved() { return saved; } - void setSaved(boolean saved) { + public void setSaved(boolean saved) { this.saved = saved; } - boolean isCrosspost() { + public boolean isCrosspost() { return isCrosspost; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java index 5a4f71ce..bf8fec96 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java @@ -11,29 +11,29 @@ import retrofit2.Call; import retrofit2.Callback; import retrofit2.Retrofit; -class PostDataSource extends PageKeyedDataSource { - - static final int TYPE_FRONT_PAGE = 0; - static final int TYPE_SUBREDDIT = 1; - static final int TYPE_USER = 2; - static final int TYPE_SEARCH = 3; - - static final String SORT_TYPE_BEST = "best"; - static final String SORT_TYPE_HOT = "hot"; - static final String SORT_TYPE_NEW = "new"; - static final String SORT_TYPE_RANDOM = "random"; - static final String SORT_TYPE_RISING = "rising"; - static final String SORT_TYPE_TOP = "top"; - static final String SORT_TYPE_CONTROVERSIAL = "controversial"; - static final String SORT_TYPE_RELEVANCE = "relevance"; - static final String SORT_TYPE_COMMENTS = "comments"; - - static final String USER_WHERE_SUBMITTED = "submitted"; - static final String USER_WHERE_UPVOTED = "upvoted"; - static final String USER_WHERE_DOWNVOTED = "downvoted"; - static final String USER_WHERE_HIDDEN = "hidden"; - static final String USER_WHERE_SAVED = "saved"; - static final String USER_WHERE_GILDED = "gilded"; +public class PostDataSource extends PageKeyedDataSource { + + public static final int TYPE_FRONT_PAGE = 0; + public static final int TYPE_SUBREDDIT = 1; + public static final int TYPE_USER = 2; + public static final int TYPE_SEARCH = 3; + + public static final String SORT_TYPE_BEST = "best"; + public static final String SORT_TYPE_HOT = "hot"; + public static final String SORT_TYPE_NEW = "new"; + public static final String SORT_TYPE_RANDOM = "random"; + public static final String SORT_TYPE_RISING = "rising"; + public static final String SORT_TYPE_TOP = "top"; + public static final String SORT_TYPE_CONTROVERSIAL = "controversial"; + public static final String SORT_TYPE_RELEVANCE = "relevance"; + public static final String SORT_TYPE_COMMENTS = "comments"; + + public static final String USER_WHERE_SUBMITTED = "submitted"; + public static final String USER_WHERE_UPVOTED = "upvoted"; + public static final String USER_WHERE_DOWNVOTED = "downvoted"; + public static final String USER_WHERE_HIDDEN = "hidden"; + public static final String USER_WHERE_SAVED = "saved"; + public static final String USER_WHERE_GILDED = "gilded"; private Retrofit retrofit; private String accessToken; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostFragment.java deleted file mode 100644 index f6d653e6..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostFragment.java +++ /dev/null @@ -1,667 +0,0 @@ -package ml.docilealligator.infinityforreddit; - - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.graphics.Rect; -import android.os.Build; -import android.os.Bundle; -import android.os.CountDownTimer; -import android.os.Handler; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.DimenRes; -import androidx.annotation.NonNull; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProvider; -import androidx.paging.PagedList; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.LinearSmoothScroller; -import androidx.recyclerview.widget.RecyclerView; -import androidx.recyclerview.widget.StaggeredGridLayoutManager; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import retrofit2.Retrofit; - - -/** - * A simple {@link Fragment} subclass. - */ -public class PostFragment extends Fragment implements FragmentCommunicator { - - static final String EXTRA_NAME = "EN"; - static final String EXTRA_USER_NAME = "EUN"; - static final String EXTRA_USER_WHERE = "EUW"; - static final String EXTRA_QUERY = "EQ"; - static final String EXTRA_POST_TYPE = "EPT"; - static final String EXTRA_SORT_TYPE = "EST"; - static final String EXTRA_FILTER = "EF"; - static final int EXTRA_NO_FILTER = -2; - static final String EXTRA_ACCESS_TOKEN = "EAT"; - - private static final String IS_IN_LAZY_MODE_STATE = "IILMS"; - private static final String RECYCLER_VIEW_POSITION_STATE = "RVPS"; - - @BindView(R.id.recycler_view_post_fragment) RecyclerView mPostRecyclerView; - @BindView(R.id.progress_bar_post_fragment) CircleProgressBar mProgressBar; - @BindView(R.id.fetch_post_info_linear_layout_post_fragment) LinearLayout mFetchPostInfoLinearLayout; - @BindView(R.id.fetch_post_info_image_view_post_fragment) ImageView mFetchPostInfoImageView; - @BindView(R.id.fetch_post_info_text_view_post_fragment) TextView mFetchPostInfoTextView; - - private RequestManager mGlide; - - private Activity activity; - private LinearLayoutManager mLinearLayoutManager; - private StaggeredGridLayoutManager mStaggeredGridLayoutManager; - - private boolean isInLazyMode = false; - private boolean isLazyModePaused = false; - private boolean hasPost = false; - - private PostRecyclerViewAdapter mAdapter; - private RecyclerView.SmoothScroller smoothScroller; - - PostViewModel mPostViewModel; - - private Window window; - private Handler lazyModeHandler; - private LazyModeRunnable lazyModeRunnable; - private CountDownTimer resumeLazyModeCountDownTimer; - - private float lazyModeInterval; - - @Inject @Named("no_oauth") - Retrofit mRetrofit; - - @Inject @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - public PostFragment() { - // Required empty public constructor - } - - @Override - public void onResume() { - super.onResume(); - if(mPostRecyclerView.getAdapter() != null) { - ((PostRecyclerViewAdapter) mPostRecyclerView.getAdapter()).setCanStartActivity(true); - } - } - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - // Inflate the layout for this fragment - View rootView = inflater.inflate(R.layout.fragment_post, container, false); - - ((Infinity) activity.getApplication()).getAppComponent().inject(this); - - ButterKnife.bind(this, rootView); - - EventBus.getDefault().register(this); - - lazyModeHandler = new Handler(); - - lazyModeInterval = Float.parseFloat(mSharedPreferences.getString(SharedPreferencesUtils.LAZY_MODE_INTERVAL_KEY, "2.5")); - - smoothScroller = new LinearSmoothScroller(activity) { - @Override - protected int getVerticalSnapPreference() { - return LinearSmoothScroller.SNAP_TO_START; - } - }; - - window = activity.getWindow(); - - Resources resources = getResources(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { - int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); - if (navBarResourceId > 0) { - mPostRecyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); - } - } - } - - if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT && !resources.getBoolean(R.bool.isTablet)) { - mLinearLayoutManager = new LinearLayoutManager(activity); - mPostRecyclerView.setLayoutManager(mLinearLayoutManager); - } else { - mStaggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); - mPostRecyclerView.setLayoutManager(mStaggeredGridLayoutManager); - StaggeredGridLayoutManagerItemOffsetDecoration itemDecoration = - new StaggeredGridLayoutManagerItemOffsetDecoration(activity, R.dimen.staggeredLayoutManagerItemOffset); - mPostRecyclerView.addItemDecoration(itemDecoration); - } - - mGlide = Glide.with(activity); - - lazyModeRunnable = new LazyModeRunnable() { - - @Override - public void run() { - if(isInLazyMode && !isLazyModePaused) { - int nPosts = mAdapter.getItemCount(); - if(getCurrentPosition() == -1) { - if(mLinearLayoutManager != null) { - setCurrentPosition(mLinearLayoutManager.findFirstVisibleItemPosition()); - } else { - int[] into = new int[2]; - setCurrentPosition(mStaggeredGridLayoutManager.findFirstVisibleItemPositions(into)[1]); - } - } - - if(getCurrentPosition() != RecyclerView.NO_POSITION && nPosts > getCurrentPosition()) { - incrementCurrentPosition(); - smoothScroller.setTargetPosition(getCurrentPosition()); - if(mLinearLayoutManager != null) { - mLinearLayoutManager.startSmoothScroll(smoothScroller); - } else { - mStaggeredGridLayoutManager.startSmoothScroll(smoothScroller); - } - } - } - lazyModeHandler.postDelayed(this, (long) (lazyModeInterval * 1000)); - } - }; - - resumeLazyModeCountDownTimer = new CountDownTimer((long) (lazyModeInterval * 1000), (long) (lazyModeInterval * 1000)) { - @Override - public void onTick(long l) { - - } - - @Override - public void onFinish() { - resumeLazyMode(true); - } - }; - - if(savedInstanceState != null) { - int recyclerViewPosition = savedInstanceState.getInt(RECYCLER_VIEW_POSITION_STATE); - if(recyclerViewPosition > 0) { - mPostRecyclerView.scrollToPosition(recyclerViewPosition); - } - - isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); - if(isInLazyMode) { - resumeLazyMode(false); - } - } - - mPostRecyclerView.setOnTouchListener((view, motionEvent) -> { - if(isInLazyMode) { - pauseLazyMode(true); - } - return false; - }); - - if(activity instanceof MainActivity) { - mPostRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { - if (dy > 0) { - ((MainActivity) activity).postScrollDown(); - } else if (dy < 0) { - ((MainActivity) activity).postScrollUp(); - } - - } - }); - } else if(activity instanceof ViewSubredditDetailActivity) { - mPostRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { - if (dy > 0) { - ((ViewSubredditDetailActivity) activity).postScrollDown(); - } else if (dy < 0) { - ((ViewSubredditDetailActivity) activity).postScrollUp(); - } - - } - }); - } - - int postType = getArguments().getInt(EXTRA_POST_TYPE); - String sortType = getArguments().getString(EXTRA_SORT_TYPE); - - int filter = getArguments().getInt(EXTRA_FILTER); - String accessToken = getArguments().getString(EXTRA_ACCESS_TOKEN); - boolean nsfw = mSharedPreferences.getBoolean(SharedPreferencesUtils.NSFW_KEY, false); - boolean needBlurNsfw = mSharedPreferences.getBoolean(SharedPreferencesUtils.BLUR_NSFW_KEY, true); - boolean needBlurSpoiler = mSharedPreferences.getBoolean(SharedPreferencesUtils.BLUR_SPOILER_KEY, false); - - PostViewModel.Factory factory; - - if(postType == PostDataSource.TYPE_SEARCH) { - String subredditName = getArguments().getString(EXTRA_NAME); - String query = getArguments().getString(EXTRA_QUERY); - - mAdapter = new PostRecyclerViewAdapter(activity, mOauthRetrofit, mRetrofit, mRedditDataRoomDatabase, - accessToken, postType, true, needBlurNsfw, needBlurSpoiler, - new PostRecyclerViewAdapter.Callback() { - @Override - public void retryLoadingMore() { - mPostViewModel.retryLoadingMore(); - } - - @Override - public void typeChipClicked(int filter) { - Intent intent = new Intent(activity, FilteredThingActivity.class); - intent.putExtra(FilteredThingActivity.EXTRA_NAME, subredditName); - intent.putExtra(FilteredThingActivity.EXTRA_QUERY, query); - intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, postType); - intent.putExtra(FilteredThingActivity.EXTRA_SORT_TYPE, sortType); - intent.putExtra(FilteredThingActivity.EXTRA_FILTER, filter); - startActivity(intent); - } - }); - - if(accessToken == null) { - factory = new PostViewModel.Factory(mRetrofit, accessToken, - getResources().getConfiguration().locale, subredditName, query, postType, - sortType, filter, nsfw); - } else { - factory = new PostViewModel.Factory(mOauthRetrofit, accessToken, - getResources().getConfiguration().locale, subredditName, query, postType, - sortType, filter, nsfw); - } - } else if(postType == PostDataSource.TYPE_SUBREDDIT) { - String subredditName = getArguments().getString(EXTRA_NAME); - - boolean displaySubredditName = subredditName != null && (subredditName.equals("popular") || subredditName.equals("all")); - mAdapter = new PostRecyclerViewAdapter(activity, mOauthRetrofit, mRetrofit, mRedditDataRoomDatabase, - accessToken, postType, displaySubredditName, needBlurNsfw, needBlurSpoiler, - new PostRecyclerViewAdapter.Callback() { - @Override - public void retryLoadingMore() { - mPostViewModel.retryLoadingMore(); - } - - @Override - public void typeChipClicked(int filter) { - Intent intent = new Intent(activity, FilteredThingActivity.class); - intent.putExtra(FilteredThingActivity.EXTRA_NAME, subredditName); - intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, postType); - intent.putExtra(FilteredThingActivity.EXTRA_SORT_TYPE, sortType); - intent.putExtra(FilteredThingActivity.EXTRA_FILTER, filter); - startActivity(intent); - } - }); - - if(accessToken == null) { - factory = new PostViewModel.Factory(mRetrofit, accessToken, - getResources().getConfiguration().locale, subredditName, postType, sortType, - filter, nsfw); - } else { - factory = new PostViewModel.Factory(mOauthRetrofit, accessToken, - getResources().getConfiguration().locale, subredditName, postType, sortType, - filter, nsfw); - } - } else if(postType == PostDataSource.TYPE_USER) { - String username = getArguments().getString(EXTRA_USER_NAME); - String where = getArguments().getString(EXTRA_USER_WHERE); - if(where != null && where.equals(PostDataSource.USER_WHERE_SUBMITTED)) { - CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) mFetchPostInfoLinearLayout.getLayoutParams(); - params.height = ViewGroup.LayoutParams.WRAP_CONTENT; - mFetchPostInfoLinearLayout.setLayoutParams(params); - } - - mAdapter = new PostRecyclerViewAdapter(activity, mOauthRetrofit, mRetrofit, mRedditDataRoomDatabase, - accessToken, postType, true, needBlurNsfw, needBlurSpoiler, - new PostRecyclerViewAdapter.Callback() { - @Override - public void retryLoadingMore() { - mPostViewModel.retryLoadingMore(); - } - - @Override - public void typeChipClicked(int filter) { - Intent intent = new Intent(activity, FilteredThingActivity.class); - intent.putExtra(FilteredThingActivity.EXTRA_NAME, username); - intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, postType); - intent.putExtra(FilteredThingActivity.EXTRA_SORT_TYPE, sortType); - intent.putExtra(FilteredThingActivity.EXTRA_USER_WHERE, where); - intent.putExtra(FilteredThingActivity.EXTRA_FILTER, filter); - startActivity(intent); - } - }); - - if(accessToken == null) { - factory = new PostViewModel.Factory(mRetrofit, accessToken, - getResources().getConfiguration().locale, username, postType, sortType, where, - filter, nsfw); - } else { - factory = new PostViewModel.Factory(mOauthRetrofit, accessToken, - getResources().getConfiguration().locale, username, postType, sortType, where, - filter, nsfw); - } - } else { - mAdapter = new PostRecyclerViewAdapter(activity, mOauthRetrofit, mRetrofit, mRedditDataRoomDatabase, - accessToken, postType, true, needBlurNsfw, needBlurSpoiler, - new PostRecyclerViewAdapter.Callback() { - @Override - public void retryLoadingMore() { - mPostViewModel.retryLoadingMore(); - } - - @Override - public void typeChipClicked(int filter) { - Intent intent = new Intent(activity, FilteredThingActivity.class); - intent.putExtra(FilteredThingActivity.EXTRA_NAME, activity.getString(R.string.best)); - intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, postType); - intent.putExtra(FilteredThingActivity.EXTRA_SORT_TYPE, sortType); - intent.putExtra(FilteredThingActivity.EXTRA_FILTER, filter); - startActivity(intent); - } - }); - - factory = new PostViewModel.Factory(mOauthRetrofit, accessToken, - getResources().getConfiguration().locale, postType, sortType, filter, nsfw); - } - - mPostRecyclerView.setAdapter(mAdapter); - - mPostViewModel = new ViewModelProvider(this, factory).get(PostViewModel.class); - mPostViewModel.getPosts().observe(this, posts -> mAdapter.submitList(posts)); - - mPostViewModel.hasPost().observe(this, hasPost -> { - this.hasPost = hasPost; - mProgressBar.setVisibility(View.GONE); - if(hasPost) { - mFetchPostInfoLinearLayout.setVisibility(View.GONE); - } else { - if(isInLazyMode) { - stopLazyMode(); - } - - mFetchPostInfoLinearLayout.setOnClickListener(view -> {}); - showErrorView(R.string.no_posts); - } - }); - - mPostViewModel.getInitialLoadingState().observe(this, networkState -> { - if(networkState.getStatus().equals(NetworkState.Status.SUCCESS)) { - mProgressBar.setVisibility(View.GONE); - } else if(networkState.getStatus().equals(NetworkState.Status.FAILED)) { - mProgressBar.setVisibility(View.GONE); - mFetchPostInfoLinearLayout.setOnClickListener(view -> refresh()); - showErrorView(R.string.load_posts_error); - } else { - mProgressBar.setVisibility(View.VISIBLE); - } - }); - - mPostViewModel.getPaginationNetworkState().observe(this, networkState -> mAdapter.setNetworkState(networkState)); - - return rootView; - } - - void changeSortType(String sortType) { - mPostViewModel.changeSortType(sortType); - } - - @Override - public void onAttach(@NonNull Context context) { - super.onAttach(context); - this.activity = (Activity) context; - } - - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean(IS_IN_LAZY_MODE_STATE, isInLazyMode); - if(mLinearLayoutManager != null) { - outState.putInt(RECYCLER_VIEW_POSITION_STATE, mLinearLayoutManager.findFirstVisibleItemPosition()); - } else if(mStaggeredGridLayoutManager != null) { - int[] into = new int[2]; - outState.putInt(RECYCLER_VIEW_POSITION_STATE, - mStaggeredGridLayoutManager.findFirstVisibleItemPositions(into)[0]); - } - } - - @Override - public void refresh() { - if(isInLazyMode) { - stopLazyMode(); - } - - mAdapter.setNetworkState(null); - mFetchPostInfoLinearLayout.setVisibility(View.GONE); - hasPost = false; - mPostViewModel.refresh(); - } - - private void showErrorView(int stringResId) { - if(activity != null && isAdded()) { - mProgressBar.setVisibility(View.GONE); - mFetchPostInfoLinearLayout.setVisibility(View.VISIBLE); - mFetchPostInfoTextView.setText(stringResId); - mGlide.load(R.drawable.error_image).into(mFetchPostInfoImageView); - } - } - - @Override - public void changeNSFW(boolean nsfw) { - mPostViewModel.changeNSFW(nsfw); - } - - @Override - public boolean startLazyMode() { - if(!hasPost) { - Toast.makeText(activity, R.string.no_posts_no_lazy_mode, Toast.LENGTH_SHORT).show(); - return false; - } - - isInLazyMode = true; - isLazyModePaused = false; - - lazyModeInterval = Float.parseFloat(mSharedPreferences.getString(SharedPreferencesUtils.LAZY_MODE_INTERVAL_KEY, "2.5")); - lazyModeHandler.postDelayed(lazyModeRunnable, (long) (lazyModeInterval * 1000)); - window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - Toast.makeText(activity, getString(R.string.lazy_mode_start, lazyModeInterval), - Toast.LENGTH_SHORT).show(); - - return true; - } - - @Override - public void stopLazyMode() { - isInLazyMode = false; - isLazyModePaused = false; - lazyModeRunnable.resetOldPosition(); - lazyModeHandler.removeCallbacks(lazyModeRunnable); - resumeLazyModeCountDownTimer.cancel(); - window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - Toast.makeText(activity, getString(R.string.lazy_mode_stop), Toast.LENGTH_SHORT).show(); - } - - @Override - public void resumeLazyMode(boolean resumeNow) { - if(isInLazyMode) { - isLazyModePaused = false; - window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - - lazyModeRunnable.resetOldPosition(); - - if(resumeNow) { - lazyModeHandler.post(lazyModeRunnable); - } else { - lazyModeHandler.postDelayed(lazyModeRunnable, (long) (lazyModeInterval * 1000)); - } - } - } - - @Override - public void pauseLazyMode(boolean startTimer) { - resumeLazyModeCountDownTimer.cancel(); - isInLazyMode = true; - isLazyModePaused = true; - lazyModeHandler.removeCallbacks(lazyModeRunnable); - window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - - if(startTimer) { - resumeLazyModeCountDownTimer.start(); - } - } - - @Override - public boolean isInLazyMode() { - return isInLazyMode; - } - - @Subscribe - public void onPostUpdateEvent(PostUpdateEventToPostList event) { - PagedList posts = mAdapter.getCurrentList(); - if (posts != null && event.positionInList >= 0 && event.positionInList < posts.size()) { - Post post = posts.get(event.positionInList); - if (post != null && post.getFullName().equals(event.post.getFullName())) { - post.setTitle(event.post.getTitle()); - post.setVoteType(event.post.getVoteType()); - post.setScore(event.post.getScore()); - post.setNSFW(event.post.isNSFW()); - post.setHidden(event.post.isHidden()); - post.setSpoiler(event.post.isSpoiler()); - post.setFlair(event.post.getFlair()); - post.setSaved(event.post.isSaved()); - mAdapter.notifyItemChanged(event.positionInList); - } - } - } - - @Subscribe - public void onChangeNSFWBlurEvent(ChangeNSFWBlurEvent event) { - mAdapter.setBlurNSFW(event.needBlurNSFW); - refreshAdapter(); - } - - @Subscribe - public void onChangeSpoilerBlurEvent(ChangeSpoilerBlurEvent event) { - mAdapter.setBlurSpoiler(event.needBlurSpoiler); - refreshAdapter(); - } - - private void refreshAdapter() { - int previousPosition = -1; - if(mLinearLayoutManager != null) { - previousPosition = mLinearLayoutManager.findFirstVisibleItemPosition(); - } else if(mStaggeredGridLayoutManager != null) { - int[] into = new int[2]; - previousPosition = mStaggeredGridLayoutManager.findFirstVisibleItemPositions(into)[0]; - } - - RecyclerView.LayoutManager layoutManager = mPostRecyclerView.getLayoutManager(); - mPostRecyclerView.setAdapter(null); - mPostRecyclerView.setLayoutManager(null); - mPostRecyclerView.setAdapter(mAdapter); - mPostRecyclerView.setLayoutManager(layoutManager); - - if(previousPosition > 0) { - mPostRecyclerView.scrollToPosition(previousPosition); - } - } - - @Override - public void onStart() { - super.onStart(); - if(isInLazyMode && isLazyModePaused) { - resumeLazyMode(false); - } - } - - @Override - public void onStop() { - super.onStop(); - if(isInLazyMode) { - pauseLazyMode(false); - } - } - - @Override - public void onDestroy() { - EventBus.getDefault().unregister(this); - super.onDestroy(); - } - - private static abstract class LazyModeRunnable implements Runnable { - private int currentPosition = -1; - - int getCurrentPosition() { - return currentPosition; - } - - void setCurrentPosition(int currentPosition) { - this.currentPosition = currentPosition; - } - - void incrementCurrentPosition() { - currentPosition++; - } - - void resetOldPosition() { - currentPosition = -1; - } - } - - private static class StaggeredGridLayoutManagerItemOffsetDecoration extends RecyclerView.ItemDecoration { - - private int mItemOffset; - - StaggeredGridLayoutManagerItemOffsetDecoration(int itemOffset) { - mItemOffset = itemOffset; - } - - StaggeredGridLayoutManagerItemOffsetDecoration(@NonNull Context context, @DimenRes int itemOffsetId) { - this(context.getResources().getDimensionPixelSize(itemOffsetId)); - } - - @Override - public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, - @NonNull RecyclerView.State state) { - super.getItemOffsets(outRect, view, parent, state); - - StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams(); - - int spanIndex = layoutParams.getSpanIndex(); - - int halfOffset = mItemOffset / 2; - - if(spanIndex == 0) { - outRect.set(0, 0, halfOffset, 0); - } else { - outRect.set(halfOffset, 0, 0, 0); - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostImageActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostImageActivity.java deleted file mode 100644 index 9fd5b45e..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostImageActivity.java +++ /dev/null @@ -1,586 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.Environment; -import android.provider.MediaStore; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.widget.Button; -import android.widget.EditText; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.constraintlayout.widget.ConstraintLayout; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.core.content.ContextCompat; -import androidx.core.content.FileProvider; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.bumptech.glide.request.RequestOptions; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import com.google.android.material.floatingactionbutton.FloatingActionButton; -import com.google.android.material.snackbar.Snackbar; -import com.libRG.CustomTextView; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import java.io.File; -import java.io.IOException; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import pl.droidsonroids.gif.GifImageView; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class PostImageActivity extends AppCompatActivity implements FlairBottomSheetFragment.FlairSelectionCallback { - - static final String EXTRA_SUBREDDIT_NAME = "ESN"; - - private static final String SUBREDDIT_NAME_STATE = "SNS"; - private static final String SUBREDDIT_ICON_STATE = "SIS"; - private static final String SUBREDDIT_SELECTED_STATE = "SSS"; - private static final String SUBREDDIT_IS_USER_STATE = "SIUS"; - private static final String IMAGE_URI_STATE = "IUS"; - private static final String LOAD_SUBREDDIT_ICON_STATE = "LSIS"; - private static final String IS_POSTING_STATE = "IPS"; - private static final String FLAIR_STATE = "FS"; - private static final String IS_SPOILER_STATE = "ISS"; - private static final String IS_NSFW_STATE = "INS"; - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - private static final String ACCOUNT_NAME_STATE = "ANS"; - - private static final int SUBREDDIT_SELECTION_REQUEST_CODE = 0; - private static final int PICK_IMAGE_REQUEST_CODE = 1; - private static final int CAPTURE_IMAGE_REQUEST_CODE = 2; - - @BindView(R.id.coordinator_layout_post_image_activity) CoordinatorLayout coordinatorLayout; - @BindView(R.id.toolbar_post_image_activity) Toolbar toolbar; - @BindView(R.id.subreddit_icon_gif_image_view_post_image_activity) GifImageView iconGifImageView; - @BindView(R.id.subreddit_name_text_view_post_image_activity) TextView subredditNameTextView; - @BindView(R.id.rules_button_post_image_activity) Button rulesButton; - @BindView(R.id.flair_custom_text_view_post_image_activity) CustomTextView flairTextView; - @BindView(R.id.spoiler_custom_text_view_post_image_activity) CustomTextView spoilerTextView; - @BindView(R.id.nsfw_custom_text_view_post_image_activity) CustomTextView nsfwTextView; - @BindView(R.id.post_title_edit_text_post_image_activity) EditText titleEditText; - @BindView(R.id.select_image_constraint_layout_post_image_activity) ConstraintLayout constraintLayout; - @BindView(R.id.capture_fab_post_image_activity) FloatingActionButton captureFab; - @BindView(R.id.select_from_library_fab_post_image_activity) FloatingActionButton selectFromLibraryFab; - @BindView(R.id.select_again_text_view_post_image_activity) TextView selectAgainTextView; - @BindView(R.id.image_view_post_image_activity) ImageView imageView; - - private boolean mNullAccessToken = false; - private String mAccessToken; - private String mAccountName; - private String iconUrl; - private String subredditName; - private boolean subredditSelected = false; - private boolean subredditIsUser; - private boolean loadSubredditIconSuccessful = true; - private boolean isPosting; - private Uri imageUri; - - private Flair flair; - private boolean isSpoiler = false; - private boolean isNSFW = false; - - private Menu mMemu; - private RequestManager mGlide; - private FlairBottomSheetFragment flairSelectionBottomSheetFragment; - private Snackbar mPostingSnackbar; - - @Inject - @Named("no_oauth") - Retrofit mRetrofit; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - @Named("upload_media") - Retrofit mUploadMediaRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_post_image); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - Window window = getWindow(); - if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - mGlide = Glide.with(this); - - mPostingSnackbar = Snackbar.make(coordinatorLayout, R.string.posting, Snackbar.LENGTH_INDEFINITE); - - if(savedInstanceState != null) { - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); - - if(!mNullAccessToken && mAccessToken == null) { - getCurrentAccount(); - } - - subredditName = savedInstanceState.getString(SUBREDDIT_NAME_STATE); - iconUrl = savedInstanceState.getString(SUBREDDIT_ICON_STATE); - subredditSelected = savedInstanceState.getBoolean(SUBREDDIT_SELECTED_STATE); - subredditIsUser = savedInstanceState.getBoolean(SUBREDDIT_IS_USER_STATE); - loadSubredditIconSuccessful = savedInstanceState.getBoolean(LOAD_SUBREDDIT_ICON_STATE); - isPosting = savedInstanceState.getBoolean(IS_POSTING_STATE); - flair = savedInstanceState.getParcelable(FLAIR_STATE); - isSpoiler = savedInstanceState.getBoolean(IS_SPOILER_STATE); - isNSFW = savedInstanceState.getBoolean(IS_NSFW_STATE); - - if(savedInstanceState.getString(IMAGE_URI_STATE) != null) { - imageUri = Uri.parse(savedInstanceState.getString(IMAGE_URI_STATE)); - loadImage(); - } - - if(subredditName != null) { - subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); - subredditNameTextView.setText(subredditName); - flairTextView.setVisibility(View.VISIBLE); - if(!loadSubredditIconSuccessful) { - loadSubredditIcon(); - } - } - displaySubredditIcon(); - - if(isPosting) { - mPostingSnackbar.show(); - } - - if(flair != null) { - flairTextView.setText(flair.getText()); - flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - } - if(isSpoiler) { - spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - } - if(isNSFW) { - nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); - } - } else { - getCurrentAccount(); - - isPosting = false; - - if(getIntent().hasExtra(EXTRA_SUBREDDIT_NAME)) { - loadSubredditIconSuccessful = false; - subredditName = getIntent().getStringExtra(EXTRA_SUBREDDIT_NAME); - subredditSelected = true; - subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); - subredditNameTextView.setText(subredditName); - loadSubredditIcon(); - } else { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(iconGifImageView); - } - - imageUri = getIntent().getData(); - if(imageUri != null) { - loadImage(); - } - } - - iconGifImageView.setOnClickListener(view -> { - Intent intent = new Intent(this, SubredditSelectionActivity.class); - startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); - }); - - subredditNameTextView.setOnClickListener(view -> { - Intent intent = new Intent(this, SubredditSelectionActivity.class); - startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); - }); - - rulesButton.setOnClickListener(view -> { - if(subredditName == null) { - Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); - } else { - Intent intent = new Intent(this, RulesActivity.class); - if(subredditIsUser) { - intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, "u_" + subredditName); - } else { - intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, subredditName); - } - startActivity(intent); - } - }); - - flairTextView.setOnClickListener(view -> { - if(flair == null) { - flairSelectionBottomSheetFragment = new FlairBottomSheetFragment(); - Bundle bundle = new Bundle(); - bundle.putString(FlairBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - bundle.putString(FlairBottomSheetFragment.EXTRA_SUBREDDIT_NAME, subredditName); - flairSelectionBottomSheetFragment.setArguments(bundle); - flairSelectionBottomSheetFragment.show(getSupportFragmentManager(), flairSelectionBottomSheetFragment.getTag()); - } else { - flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - flairTextView.setText(getString(R.string.flair)); - flair = null; - } - }); - - spoilerTextView.setOnClickListener(view -> { - if(!isSpoiler) { - spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - isSpoiler = true; - } else { - spoilerTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - isSpoiler = false; - } - }); - - nsfwTextView.setOnClickListener(view -> { - if(!isNSFW) { - nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); - isNSFW = true; - } else { - nsfwTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - isNSFW = false; - } - }); - - captureFab.setOnClickListener(view -> { - Intent pictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - if(pictureIntent.resolveActivity(getPackageManager()) != null) { - try { - imageUri = FileProvider.getUriForFile(this, "ml.docilealligator.infinityforreddit.provider", - File.createTempFile("temp_img", ".jpg", getExternalFilesDir(Environment.DIRECTORY_PICTURES))); - pictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); - startActivityForResult(pictureIntent, CAPTURE_IMAGE_REQUEST_CODE); - } catch (IOException ex) { - Snackbar.make(coordinatorLayout, R.string.error_creating_temp_file, Snackbar.LENGTH_SHORT).show(); - } - } else { - Snackbar.make(coordinatorLayout, R.string.no_camera_available, Snackbar.LENGTH_SHORT).show(); - } - }); - - selectFromLibraryFab.setOnClickListener(view -> { - Intent intent = new Intent(); - intent.setType("image/*"); - intent.setAction(Intent.ACTION_GET_CONTENT); - startActivityForResult(Intent.createChooser(intent,getResources().getString(R.string.select_from_gallery)), PICK_IMAGE_REQUEST_CODE); - }); - - selectAgainTextView.setOnClickListener(view -> { - imageUri = null; - selectAgainTextView.setVisibility(View.GONE); - mGlide.clear(imageView); - imageView.setVisibility(View.GONE); - constraintLayout.setVisibility(View.VISIBLE); - }); - } - - private void getCurrentAccount() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - } - }).execute(); - } - - private void loadImage() { - constraintLayout.setVisibility(View.GONE); - imageView.setVisibility(View.VISIBLE); - selectAgainTextView.setVisibility(View.VISIBLE); - mGlide.load(imageUri).into(imageView); - } - - private void displaySubredditIcon() { - if(iconUrl != null && !iconUrl.equals("")) { - mGlide.load(iconUrl) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(iconGifImageView); - } else { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(iconGifImageView); - } - } - - private void loadSubredditIcon() { - new LoadSubredditIconAsyncTask(mRedditDataRoomDatabase, subredditName, mRetrofit, iconImageUrl -> { - iconUrl = iconImageUrl; - displaySubredditIcon(); - loadSubredditIconSuccessful = true; - }).execute(); - } - - private void promptAlertDialog(int titleResId, int messageResId) { - new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme) - .setTitle(titleResId) - .setMessage(messageResId) - .setPositiveButton(R.string.yes, (dialogInterface, i) - -> finish()) - .setNegativeButton(R.string.no, null) - .show(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.post_image_activity, menu); - mMemu = menu; - if(isPosting) { - mMemu.findItem(R.id.action_send_post_image_activity).setEnabled(false); - mMemu.findItem(R.id.action_send_post_image_activity).getIcon().setAlpha(130); - } - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - if(isPosting) { - promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); - return true; - } else { - if(!titleEditText.getText().toString().equals("") || imageUri != null) { - promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); - return true; - } - } - finish(); - return true; - case R.id.action_send_post_image_activity: - if(!subredditSelected) { - Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); - return true; - } - - if(titleEditText.getText() == null || titleEditText.getText().toString().equals("")) { - Snackbar.make(coordinatorLayout, R.string.title_required, Snackbar.LENGTH_SHORT).show(); - return true; - } - - if(imageUri == null) { - Snackbar.make(coordinatorLayout, R.string.select_an_image, Snackbar.LENGTH_SHORT).show(); - return true; - } - - isPosting = true; - - item.setEnabled(false); - item.getIcon().setAlpha(130); - - mPostingSnackbar.show(); - - String subredditName; - if(subredditIsUser) { - subredditName = "u_" + subredditNameTextView.getText().toString(); - } else { - subredditName = subredditNameTextView.getText().toString(); - } - - Intent intent = new Intent(this, SubmitPostService.class); - intent.setData(imageUri); - intent.putExtra(SubmitPostService.EXTRA_ACCESS_TOKEN, mAccessToken); - intent.putExtra(SubmitPostService.EXTRA_SUBREDDIT_NAME, subredditName); - intent.putExtra(SubmitPostService.EXTRA_TITLE, titleEditText.getText().toString()); - intent.putExtra(SubmitPostService.EXTRA_FLAIR, flair); - intent.putExtra(SubmitPostService.EXTRA_IS_SPOILER, isSpoiler); - intent.putExtra(SubmitPostService.EXTRA_IS_NSFW, isNSFW); - intent.putExtra(SubmitPostService.EXTRA_POST_TYPE, SubmitPostService.EXTRA_POST_TYPE_IMAGE); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - startForegroundService(intent); - } else { - startService(intent); - } - - return true; - } - - return false; - } - - @Override - public void onBackPressed() { - if(isPosting) { - promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); - } else { - if(!titleEditText.getText().toString().equals("") || imageUri != null) { - promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); - } else { - finish(); - } - } - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putString(SUBREDDIT_NAME_STATE, subredditName); - outState.putString(SUBREDDIT_ICON_STATE, iconUrl); - outState.putBoolean(SUBREDDIT_SELECTED_STATE, subredditSelected); - outState.putBoolean(SUBREDDIT_IS_USER_STATE, subredditIsUser); - if(imageUri != null) { - outState.putString(IMAGE_URI_STATE, imageUri.toString()); - } - outState.putBoolean(LOAD_SUBREDDIT_ICON_STATE, loadSubredditIconSuccessful); - outState.putBoolean(IS_POSTING_STATE, isPosting); - outState.putParcelable(FLAIR_STATE, flair); - outState.putBoolean(IS_SPOILER_STATE, isSpoiler); - outState.putBoolean(IS_NSFW_STATE, isNSFW); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - outState.putString(ACCOUNT_NAME_STATE, mAccountName); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if(requestCode == SUBREDDIT_SELECTION_REQUEST_CODE) { - if(resultCode == RESULT_OK) { - subredditName = data.getExtras().getString(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_NAME); - iconUrl = data.getExtras().getString(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_ICON_URL); - subredditSelected = true; - subredditIsUser = data.getExtras().getBoolean(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_IS_USER); - - subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); - subredditNameTextView.setText(subredditName); - displaySubredditIcon(); - - flairTextView.setVisibility(View.VISIBLE); - flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - flairTextView.setText(getString(R.string.flair)); - flair = null; - } - } else if(requestCode == PICK_IMAGE_REQUEST_CODE) { - if(resultCode == RESULT_OK) { - if(data == null) { - Snackbar.make(coordinatorLayout, R.string.error_getting_image, Snackbar.LENGTH_SHORT).show(); - return; - } - - imageUri = data.getData(); - loadImage(); - } - } else if(requestCode == CAPTURE_IMAGE_REQUEST_CODE) { - if(resultCode == RESULT_OK) { - loadImage(); - } - } - } - - @Override - protected void onDestroy() { - EventBus.getDefault().unregister(this); - super.onDestroy(); - } - - @Override - public void flairSelected(Flair flair) { - this.flair = flair; - flairTextView.setText(flair.getText()); - flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } - - @Subscribe - public void onSubmitImagePostEvent(SubmitImagePostEvent submitImagePostEvent) { - isPosting = false; - mPostingSnackbar.dismiss(); - if(submitImagePostEvent.postSuccess) { - Intent intent = new Intent(PostImageActivity.this, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mAccountName); - startActivity(intent); - finish(); - } else { - mMemu.findItem(R.id.action_send_post_image_activity).setEnabled(true); - mMemu.findItem(R.id.action_send_post_image_activity).getIcon().setAlpha(255); - if (submitImagePostEvent.errorMessage == null || submitImagePostEvent.errorMessage.equals("")) { - Snackbar.make(coordinatorLayout, R.string.post_failed, Snackbar.LENGTH_SHORT).show(); - } else { - Snackbar.make(coordinatorLayout, submitImagePostEvent.errorMessage.substring(0, 1).toUpperCase() - + submitImagePostEvent.errorMessage.substring(1), Snackbar.LENGTH_SHORT).show(); - } - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostLinkActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostLinkActivity.java deleted file mode 100644 index e5a2843a..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostLinkActivity.java +++ /dev/null @@ -1,495 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.widget.Button; -import android.widget.EditText; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.core.content.ContextCompat; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.bumptech.glide.request.RequestOptions; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import com.google.android.material.snackbar.Snackbar; -import com.libRG.CustomTextView; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import pl.droidsonroids.gif.GifImageView; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class PostLinkActivity extends AppCompatActivity implements FlairBottomSheetFragment.FlairSelectionCallback { - - static final String EXTRA_SUBREDDIT_NAME = "ESN"; - static final String EXTRA_LINK = "EL"; - - private static final String SUBREDDIT_NAME_STATE = "SNS"; - private static final String SUBREDDIT_ICON_STATE = "SIS"; - private static final String SUBREDDIT_SELECTED_STATE = "SSS"; - private static final String SUBREDDIT_IS_USER_STATE = "SIUS"; - private static final String LOAD_SUBREDDIT_ICON_STATE = "LSIS"; - private static final String IS_POSTING_STATE = "IPS"; - private static final String FLAIR_STATE = "FS"; - private static final String IS_SPOILER_STATE = "ISS"; - private static final String IS_NSFW_STATE = "INS"; - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - - private static final int SUBREDDIT_SELECTION_REQUEST_CODE = 0; - - @BindView(R.id.coordinator_layout_post_link_activity) CoordinatorLayout coordinatorLayout; - @BindView(R.id.toolbar_post_link_activity) Toolbar toolbar; - @BindView(R.id.subreddit_icon_gif_image_view_post_link_activity) GifImageView iconGifImageView; - @BindView(R.id.subreddit_name_text_view_post_link_activity) TextView subredditNameTextView; - @BindView(R.id.rules_button_post_link_activity) Button rulesButton; - @BindView(R.id.flair_custom_text_view_post_link_activity) CustomTextView flairTextView; - @BindView(R.id.spoiler_custom_text_view_post_link_activity) CustomTextView spoilerTextView; - @BindView(R.id.nsfw_custom_text_view_post_link_activity) CustomTextView nsfwTextView; - @BindView(R.id.post_title_edit_text_post_link_activity) EditText titleEditText; - @BindView(R.id.post_link_edit_text_post_link_activity) EditText contentEditText; - - private boolean mNullAccessToken = false; - private String mAccessToken; - private String iconUrl; - private String subredditName; - private boolean subredditSelected = false; - private boolean subredditIsUser; - private boolean loadSubredditIconSuccessful = true; - private boolean isPosting; - - private Flair flair; - private boolean isSpoiler = false; - private boolean isNSFW = false; - - private Menu mMemu; - private RequestManager mGlide; - private FlairBottomSheetFragment flairSelectionBottomSheetFragment; - private Snackbar mPostingSnackbar; - - @Inject - @Named("no_oauth") - Retrofit mRetrofit; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_post_link); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - Window window = getWindow(); - if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - mGlide = Glide.with(this); - - mPostingSnackbar = Snackbar.make(coordinatorLayout, R.string.posting, Snackbar.LENGTH_INDEFINITE); - - if(savedInstanceState != null) { - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - - if(!mNullAccessToken && mAccessToken == null) { - getCurrentAccount(); - } - - subredditName = savedInstanceState.getString(SUBREDDIT_NAME_STATE); - iconUrl = savedInstanceState.getString(SUBREDDIT_ICON_STATE); - subredditSelected = savedInstanceState.getBoolean(SUBREDDIT_SELECTED_STATE); - subredditIsUser = savedInstanceState.getBoolean(SUBREDDIT_IS_USER_STATE); - loadSubredditIconSuccessful = savedInstanceState.getBoolean(LOAD_SUBREDDIT_ICON_STATE); - isPosting = savedInstanceState.getBoolean(IS_POSTING_STATE); - flair = savedInstanceState.getParcelable(FLAIR_STATE); - isSpoiler = savedInstanceState.getBoolean(IS_SPOILER_STATE); - isNSFW = savedInstanceState.getBoolean(IS_NSFW_STATE); - - if(subredditName != null) { - subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); - subredditNameTextView.setText(subredditName); - flairTextView.setVisibility(View.VISIBLE); - if(!loadSubredditIconSuccessful) { - loadSubredditIcon(); - } - } - displaySubredditIcon(); - - if(isPosting) { - mPostingSnackbar.show(); - } - - if(flair != null) { - flairTextView.setText(flair.getText()); - flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - } - if(isSpoiler) { - spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - } - if(isNSFW) { - nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); - } - } else { - getCurrentAccount(); - - isPosting = false; - - if(getIntent().hasExtra(EXTRA_SUBREDDIT_NAME)) { - loadSubredditIconSuccessful = false; - subredditName = getIntent().getStringExtra(EXTRA_SUBREDDIT_NAME); - subredditSelected = true; - subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); - subredditNameTextView.setText(subredditName); - flairTextView.setVisibility(View.VISIBLE); - loadSubredditIcon(); - } else { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(iconGifImageView); - } - - String link = getIntent().getStringExtra(EXTRA_LINK); - if(link != null) { - contentEditText.setText(link); - } - } - - iconGifImageView.setOnClickListener(view -> { - Intent intent = new Intent(this, SubredditSelectionActivity.class); - startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); - }); - - subredditNameTextView.setOnClickListener(view -> { - Intent intent = new Intent(this, SubredditSelectionActivity.class); - startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); - }); - - rulesButton.setOnClickListener(view -> { - if(subredditName == null) { - Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); - } else { - Intent intent = new Intent(this, RulesActivity.class); - if(subredditIsUser) { - intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, "u_" + subredditName); - } else { - intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, subredditName); - } - startActivity(intent); - } - }); - - flairTextView.setOnClickListener(view -> { - if(flair == null) { - flairSelectionBottomSheetFragment = new FlairBottomSheetFragment(); - Bundle bundle = new Bundle(); - bundle.putString(FlairBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - bundle.putString(FlairBottomSheetFragment.EXTRA_SUBREDDIT_NAME, subredditName); - flairSelectionBottomSheetFragment.setArguments(bundle); - flairSelectionBottomSheetFragment.show(getSupportFragmentManager(), flairSelectionBottomSheetFragment.getTag()); - } else { - flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - flairTextView.setText(getString(R.string.flair)); - flair = null; - } - }); - - spoilerTextView.setOnClickListener(view -> { - if(!isSpoiler) { - spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - isSpoiler = true; - } else { - spoilerTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - isSpoiler = false; - } - }); - - nsfwTextView.setOnClickListener(view -> { - if(!isNSFW) { - nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); - isNSFW = true; - } else { - nsfwTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - isNSFW = false; - } - }); - } - - private void getCurrentAccount() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - } - }).execute(); - } - - private void displaySubredditIcon() { - if(iconUrl != null && !iconUrl.equals("")) { - mGlide.load(iconUrl) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(iconGifImageView); - } else { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(iconGifImageView); - } - } - - private void loadSubredditIcon() { - new LoadSubredditIconAsyncTask(mRedditDataRoomDatabase, subredditName, mRetrofit, iconImageUrl -> { - iconUrl = iconImageUrl; - displaySubredditIcon(); - loadSubredditIconSuccessful = true; - }).execute(); - } - - private void promptAlertDialog(int titleResId, int messageResId) { - new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme) - .setTitle(titleResId) - .setMessage(messageResId) - .setPositiveButton(R.string.yes, (dialogInterface, i) -> finish()) - .setNegativeButton(R.string.no, null) - .show(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.post_link_activity, menu); - mMemu = menu; - if(isPosting) { - mMemu.findItem(R.id.action_send_post_link_activity).setEnabled(false); - mMemu.findItem(R.id.action_send_post_link_activity).getIcon().setAlpha(130); - } - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - if(isPosting) { - promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); - return true; - } else { - if(!titleEditText.getText().toString().equals("") || !contentEditText.getText().toString().equals("")) { - promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); - return true; - } - } - finish(); - return true; - case R.id.action_send_post_link_activity: - if(!subredditSelected) { - Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); - return true; - } - - if(titleEditText.getText() == null || titleEditText.getText().toString().equals("")) { - Snackbar.make(coordinatorLayout, R.string.title_required, Snackbar.LENGTH_SHORT).show(); - return true; - } - - if(contentEditText.getText() == null || contentEditText.getText().toString().equals("")) { - Snackbar.make(coordinatorLayout, R.string.link_required, Snackbar.LENGTH_SHORT).show(); - return true; - } - - isPosting = true; - - item.setEnabled(false); - item.getIcon().setAlpha(130); - - mPostingSnackbar.show(); - - String subredditName; - if(subredditIsUser) { - subredditName = "u_" + subredditNameTextView.getText().toString(); - } else { - subredditName = subredditNameTextView.getText().toString(); - } - - Intent intent = new Intent(this, SubmitPostService.class); - intent.putExtra(SubmitPostService.EXTRA_ACCESS_TOKEN, mAccessToken); - intent.putExtra(SubmitPostService.EXTRA_SUBREDDIT_NAME, subredditName); - intent.putExtra(SubmitPostService.EXTRA_TITLE, titleEditText.getText().toString()); - intent.putExtra(SubmitPostService.EXTRA_CONTENT, contentEditText.getText().toString()); - intent.putExtra(SubmitPostService.EXTRA_KIND, RedditUtils.KIND_LINK); - intent.putExtra(SubmitPostService.EXTRA_FLAIR, flair); - intent.putExtra(SubmitPostService.EXTRA_IS_SPOILER, isSpoiler); - intent.putExtra(SubmitPostService.EXTRA_IS_NSFW, isNSFW); - intent.putExtra(SubmitPostService.EXTRA_POST_TYPE, SubmitPostService.EXTRA_POST_TEXT_OR_LINK); - startService(intent); - - return true; - } - - return false; - } - - @Override - public void onBackPressed() { - if(isPosting) { - promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); - } else { - if(!titleEditText.getText().toString().equals("") || !contentEditText.getText().toString().equals("")) { - promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); - } else { - finish(); - } - } - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putString(SUBREDDIT_NAME_STATE, subredditName); - outState.putString(SUBREDDIT_ICON_STATE, iconUrl); - outState.putBoolean(SUBREDDIT_SELECTED_STATE, subredditSelected); - outState.putBoolean(SUBREDDIT_IS_USER_STATE, subredditIsUser); - outState.putBoolean(LOAD_SUBREDDIT_ICON_STATE, loadSubredditIconSuccessful); - outState.putBoolean(IS_POSTING_STATE, isPosting); - outState.putParcelable(FLAIR_STATE, flair); - outState.putBoolean(IS_SPOILER_STATE, isSpoiler); - outState.putBoolean(IS_NSFW_STATE, isNSFW); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if(requestCode == SUBREDDIT_SELECTION_REQUEST_CODE) { - if(resultCode == RESULT_OK) { - subredditName = data.getExtras().getString(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_NAME); - iconUrl = data.getExtras().getString(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_ICON_URL); - subredditSelected = true; - subredditIsUser = data.getExtras().getBoolean(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_IS_USER); - - subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); - subredditNameTextView.setText(subredditName); - displaySubredditIcon(); - - flairTextView.setVisibility(View.VISIBLE); - flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - flairTextView.setText(getString(R.string.flair)); - flair = null; - } - } - } - - @Override - protected void onDestroy() { - EventBus.getDefault().unregister(this); - super.onDestroy(); - } - - @Override - public void flairSelected(Flair flair) { - this.flair = flair; - flairTextView.setText(flair.getText()); - flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } - - @Subscribe - public void onSubmitLinkPostEvent(SubmitTextOrLinkPostEvent submitTextOrLinkPostEvent) { - isPosting = false; - mPostingSnackbar.dismiss(); - if(submitTextOrLinkPostEvent.postSuccess) { - Intent intent = new Intent(PostLinkActivity.this, ViewPostDetailActivity.class); - intent.putExtra(ViewPostDetailActivity.EXTRA_POST_DATA, submitTextOrLinkPostEvent.post); - startActivity(intent); - finish(); - } else { - mMemu.findItem(R.id.action_send_post_link_activity).setEnabled(true); - mMemu.findItem(R.id.action_send_post_link_activity).getIcon().setAlpha(255); - if(submitTextOrLinkPostEvent.errorMessage == null) { - Snackbar.make(coordinatorLayout, R.string.post_failed, Snackbar.LENGTH_SHORT).show(); - } else { - Snackbar.make(coordinatorLayout, submitTextOrLinkPostEvent.errorMessage.substring(0, 1).toUpperCase() - + submitTextOrLinkPostEvent.errorMessage.substring(1), Snackbar.LENGTH_SHORT).show(); - } - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java deleted file mode 100644 index f6dc6970..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java +++ /dev/null @@ -1,859 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.Intent; -import android.graphics.ColorFilter; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.RelativeLayout; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.cardview.widget.CardView; -import androidx.core.content.ContextCompat; -import androidx.paging.PagedListAdapter; -import androidx.recyclerview.widget.DiffUtil; -import androidx.recyclerview.widget.RecyclerView; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestBuilder; -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.RequestOptions; -import com.bumptech.glide.request.target.Target; -import com.google.android.material.card.MaterialCardView; -import com.libRG.CustomTextView; - -import org.greenrobot.eventbus.EventBus; - -import ml.docilealligator.infinityforreddit.CustomView.AspectRatioGifImageView; -import ml.docilealligator.infinityforreddit.User.UserDao; -import butterknife.BindView; -import butterknife.ButterKnife; -import jp.wasabeef.glide.transformations.BlurTransformation; -import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import retrofit2.Retrofit; - -/** - * Created by alex on 2/25/18. - */ - -class PostRecyclerViewAdapter extends PagedListAdapter { - private Context mContext; - private Retrofit mOauthRetrofit; - private Retrofit mRetrofit; - private String mAccessToken; - private RequestManager mGlide; - private RedditDataRoomDatabase mRedditDataRoomDatabase; - private UserDao mUserDao; - private boolean canStartActivity = true; - private int mPostType; - private boolean mDisplaySubredditName; - private boolean mNeedBlurNSFW; - private boolean mNeedBlurSpoiler; - - private static final int VIEW_TYPE_DATA = 0; - private static final int VIEW_TYPE_ERROR = 1; - private static final int VIEW_TYPE_LOADING = 2; - - private NetworkState networkState; - private Callback mCallback; - - interface Callback { - void retryLoadingMore(); - void typeChipClicked(int filter); - } - - PostRecyclerViewAdapter(Context context, Retrofit oauthRetrofit, Retrofit retrofit, - RedditDataRoomDatabase redditDataRoomDatabase, String accessToken, - int postType, boolean displaySubredditName, boolean needBlurNSFW, - boolean needBlurSpoiler, Callback callback) { - super(DIFF_CALLBACK); - if(context != null) { - mContext = context; - mOauthRetrofit = oauthRetrofit; - mRetrofit = retrofit; - mAccessToken = accessToken; - mPostType = postType; - mDisplaySubredditName = displaySubredditName; - mNeedBlurNSFW = needBlurNSFW; - mNeedBlurSpoiler = needBlurSpoiler; - mGlide = Glide.with(mContext.getApplicationContext()); - mRedditDataRoomDatabase = redditDataRoomDatabase; - mUserDao = redditDataRoomDatabase.userDao(); - mCallback = callback; - } - } - - private static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() { - @Override - public boolean areItemsTheSame(@NonNull Post post, @NonNull Post t1) { - return post.getId().equals(t1.getId()); - } - - @Override - public boolean areContentsTheSame(@NonNull Post post, @NonNull Post t1) { - return post.getTitle().equals(t1.getTitle()) && !(post.getSelfText() != null && t1.getSelfText() != null - && !post.getSelfText().equals(t1.getSelfText())) - && post.getScore() == t1.getScore() && post.getVoteType() == t1.getVoteType(); - } - }; - - void setCanStartActivity(boolean canStartActivity) { - this.canStartActivity = canStartActivity; - } - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - if(viewType == VIEW_TYPE_DATA) { - CardView cardView = (CardView) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_post, parent, false); - return new DataViewHolder(cardView); - } else if(viewType == VIEW_TYPE_ERROR) { - RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_error, parent, false); - return new ErrorViewHolder(relativeLayout); - } else { - RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_loading, parent, false); - return new LoadingViewHolder(relativeLayout); - } - } - - @Override - public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) { - if(holder instanceof DataViewHolder) { - Post post = getItem(position); - if(post != null) { - final String id = post.getFullName(); - final String subredditNamePrefixed = post.getSubredditNamePrefixed(); - String subredditName = subredditNamePrefixed.substring(2); - String authorPrefixed = "u/" + post.getAuthor(); - final String postTime = post.getPostTime(); - final String title = post.getTitle(); - final String permalink = post.getPermalink(); - int voteType = post.getVoteType(); - int gilded = post.getGilded(); - boolean nsfw = post.isNSFW(); - boolean spoiler = post.isSpoiler(); - String flair = post.getFlair(); - boolean isArchived = post.isArchived(); - - ((DataViewHolder) holder).cardView.setOnClickListener(view -> { - if(canStartActivity) { - canStartActivity = false; - - Intent intent = new Intent(mContext, ViewPostDetailActivity.class); - intent.putExtra(ViewPostDetailActivity.EXTRA_POST_DATA, post); - intent.putExtra(ViewPostDetailActivity.EXTRA_POST_LIST_POSITION, position); - mContext.startActivity(intent); - } - }); - - if(mDisplaySubredditName) { - if(authorPrefixed.equals(subredditNamePrefixed)) { - if(post.getAuthorIconUrl() == null) { - new LoadUserDataAsyncTask(mUserDao, post.getAuthor(), mRetrofit, iconImageUrl -> { - if(mContext != null && getItemCount() > 0) { - if(iconImageUrl == null || iconImageUrl.equals("")) { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(((DataViewHolder) holder).iconGifImageView); - } else { - mGlide.load(iconImageUrl) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(((DataViewHolder) holder).iconGifImageView); - } - - if(holder.getAdapterPosition() >= 0) { - post.setAuthorIconUrl(iconImageUrl); - } - } - }).execute(); - } else if(!post.getAuthorIconUrl().equals("")) { - mGlide.load(post.getAuthorIconUrl()) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(((DataViewHolder) holder).iconGifImageView); - } else { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(((DataViewHolder) holder).iconGifImageView); - } - } else { - if(post.getSubredditIconUrl() == null) { - new LoadSubredditIconAsyncTask(mRedditDataRoomDatabase, subredditName, mRetrofit, - iconImageUrl -> { - if(mContext != null && getItemCount() > 0) { - if(iconImageUrl == null || iconImageUrl.equals("")) { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(((DataViewHolder) holder).iconGifImageView); - } else { - mGlide.load(iconImageUrl) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(((DataViewHolder) holder).iconGifImageView); - } - - if(holder.getAdapterPosition() >= 0) { - post.setSubredditIconUrl(iconImageUrl); - } - } - }).execute(); - } else if(!post.getSubredditIconUrl().equals("")) { - mGlide.load(post.getSubredditIconUrl()) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(((DataViewHolder) holder).iconGifImageView); - } else { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(((DataViewHolder) holder).iconGifImageView); - } - } - - ((DataViewHolder) holder).nameTextView.setTextColor(mContext.getResources().getColor(R.color.colorAccent)); - ((DataViewHolder) holder).nameTextView.setText(subredditNamePrefixed); - - ((DataViewHolder) holder).iconNameLinearLayout.setOnClickListener(view -> { - if(canStartActivity) { - canStartActivity = false; - if(post.getSubredditNamePrefixed().startsWith("u/")) { - Intent intent = new Intent(mContext, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, - post.getSubredditNamePrefixed().substring(2)); - mContext.startActivity(intent); - } else { - Intent intent = new Intent(mContext, ViewSubredditDetailActivity.class); - intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, - post.getSubredditNamePrefixed().substring(2)); - mContext.startActivity(intent); - } - } - }); - } else { - if(post.getAuthorIconUrl() == null) { - String authorName = post.getAuthor().equals("[deleted]") ? post.getSubredditNamePrefixed().substring(2) : post.getAuthor(); - new LoadUserDataAsyncTask(mUserDao, authorName, mRetrofit, iconImageUrl -> { - if(mContext != null && getItemCount() > 0) { - if(iconImageUrl == null || iconImageUrl.equals("")) { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(((DataViewHolder) holder).iconGifImageView); - } else { - mGlide.load(iconImageUrl) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(((DataViewHolder) holder).iconGifImageView); - } - - if(holder.getAdapterPosition() >= 0) { - post.setAuthorIconUrl(iconImageUrl); - } - } - }).execute(); - } else if(!post.getAuthorIconUrl().equals("")) { - mGlide.load(post.getAuthorIconUrl()) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(((DataViewHolder) holder).iconGifImageView); - } else { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(((DataViewHolder) holder).iconGifImageView); - } - - ((DataViewHolder) holder).nameTextView.setTextColor(mContext.getResources().getColor(R.color.colorPrimaryDarkDayNightTheme)); - ((DataViewHolder) holder).nameTextView.setText(authorPrefixed); - - ((DataViewHolder) holder).iconNameLinearLayout.setOnClickListener(view -> { - if(canStartActivity) { - canStartActivity = false; - Intent intent = new Intent(mContext, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, post.getAuthor()); - mContext.startActivity(intent); - } - }); - } - - ((DataViewHolder) holder).postTimeTextView.setText(postTime); - ((DataViewHolder) holder).titleTextView.setText(title); - ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + post.getVoteType())); - - if(gilded > 0) { - ((DataViewHolder) holder).gildedImageView.setVisibility(View.VISIBLE); - ((DataViewHolder) holder).gildedNumberTextView.setVisibility(View.VISIBLE); - String gildedNumber = mContext.getResources().getString(R.string.gilded_count, gilded); - ((DataViewHolder) holder).gildedNumberTextView.setText(gildedNumber); - } - - if(post.isLocked()) { - ((DataViewHolder) holder).lockedImageView.setVisibility(View.VISIBLE); - } - - if(nsfw) { - if(!(mContext instanceof FilteredThingActivity)) { - ((DataViewHolder) holder).nsfwTextView.setOnClickListener(view -> { - Intent intent = new Intent(mContext, FilteredThingActivity.class); - intent.putExtra(FilteredThingActivity.EXTRA_NAME, post.getSubredditNamePrefixed().substring(2)); - intent.putExtra(FilteredThingActivity.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); - intent.putExtra(FilteredThingActivity.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_HOT); - intent.putExtra(FilteredThingActivity.EXTRA_FILTER, Post.NSFW_TYPE); - mContext.startActivity(intent); - }); - } - ((DataViewHolder) holder).nsfwTextView.setVisibility(View.VISIBLE); - } - - if(spoiler || flair != null) { - ((DataViewHolder) holder).spoilerFlairLinearLayout.setVisibility(View.VISIBLE); - } - - if(spoiler) { - ((DataViewHolder) holder).spoilerTextView.setVisibility(View.VISIBLE); - } - - if(flair != null) { - ((DataViewHolder) holder).flairTextView.setVisibility(View.VISIBLE); - ((DataViewHolder) holder).flairTextView.setText(flair); - } - - switch (voteType) { - case 1: - //Upvoted - ((DataViewHolder) holder).upvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.upvoted)); - break; - case -1: - //Downvoted - ((DataViewHolder) holder).downvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.downvoted)); - break; - } - - if(post.getPostType() != Post.TEXT_TYPE && post.getPostType() != Post.NO_PREVIEW_LINK_TYPE) { - ((DataViewHolder) holder).relativeLayout.setVisibility(View.VISIBLE); - ((DataViewHolder) holder).progressBar.setVisibility(View.VISIBLE); - ((DataViewHolder) holder).imageView.setVisibility(View.VISIBLE); - ((DataViewHolder) holder).imageView - .setRatio((float) post.getPreviewHeight() / post.getPreviewWidth()); - loadImage(holder, post); - } - - if(mPostType == PostDataSource.TYPE_SUBREDDIT && !mDisplaySubredditName && post.isStickied()) { - ((DataViewHolder) holder).stickiedPostImageView.setVisibility(View.VISIBLE); - mGlide.load(R.drawable.ic_thumbtack_24dp).into(((DataViewHolder) holder).stickiedPostImageView); - } - - if(isArchived) { - ((DataViewHolder) holder).archivedImageView.setVisibility(View.VISIBLE); - - ((DataViewHolder) holder).upvoteButton - .setColorFilter(ContextCompat.getColor(mContext, R.color.voteAndReplyUnavailableVoteButtonColor), android.graphics.PorterDuff.Mode.SRC_IN); - ((DataViewHolder) holder).downvoteButton - .setColorFilter(ContextCompat.getColor(mContext, R.color.voteAndReplyUnavailableVoteButtonColor), android.graphics.PorterDuff.Mode.SRC_IN); - } - - if(post.isCrosspost()) { - ((DataViewHolder) holder).crosspostImageView.setVisibility(View.VISIBLE); - } - - if(!(mContext instanceof FilteredThingActivity)) { - ((DataViewHolder) holder).typeTextView.setOnClickListener(view -> mCallback.typeChipClicked(post.getPostType())); - } - - switch (post.getPostType()) { - case Post.IMAGE_TYPE: - ((DataViewHolder) holder).typeTextView.setText(R.string.image); - - final String imageUrl = post.getUrl(); - ((DataViewHolder) holder).imageView.setOnClickListener(view -> { - Intent intent = new Intent(mContext, ViewImageActivity.class); - intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, imageUrl); - intent.putExtra(ViewImageActivity.TITLE_KEY, title); - intent.putExtra(ViewImageActivity.FILE_NAME_KEY, subredditNamePrefixed.substring(2) - + "-" + id.substring(3)); - mContext.startActivity(intent); - }); - break; - case Post.LINK_TYPE: - ((DataViewHolder) holder).typeTextView.setText(R.string.link); - - ((DataViewHolder) holder).linkTextView.setVisibility(View.VISIBLE); - String domain = Uri.parse(post.getUrl()).getHost(); - ((DataViewHolder) holder).linkTextView.setText(domain); - - ((DataViewHolder) holder).imageView.setOnClickListener(view -> { - Intent intent = new Intent(mContext, LinkResolverActivity.class); - Uri uri = Uri.parse(post.getUrl()); - if(uri.getScheme() == null && uri.getHost() == null) { - intent.setData(LinkResolverActivity.getRedditUriByPath(post.getUrl())); - } else { - intent.setData(uri); - } - mContext.startActivity(intent); - }); - break; - case Post.GIF_VIDEO_TYPE: - ((DataViewHolder) holder).typeTextView.setText(R.string.gif); - - final Uri gifVideoUri = Uri.parse(post.getVideoUrl()); - ((DataViewHolder) holder).imageView.setOnClickListener(view -> { - Intent intent = new Intent(mContext, ViewVideoActivity.class); - intent.setData(gifVideoUri); - intent.putExtra(ViewVideoActivity.TITLE_KEY, title); - intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, subredditName); - intent.putExtra(ViewVideoActivity.ID_KEY, id); - mContext.startActivity(intent); - }); - break; - case Post.VIDEO_TYPE: - ((DataViewHolder) holder).typeTextView.setText(R.string.video); - - final Uri videoUri = Uri.parse(post.getVideoUrl()); - ((DataViewHolder) holder).imageView.setOnClickListener(view -> { - Intent intent = new Intent(mContext, ViewVideoActivity.class); - intent.setData(videoUri); - intent.putExtra(ViewVideoActivity.TITLE_KEY, title); - intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, subredditName); - intent.putExtra(ViewVideoActivity.ID_KEY, id); - mContext.startActivity(intent); - }); - break; - case Post.NO_PREVIEW_LINK_TYPE: - ((DataViewHolder) holder).typeTextView.setText(R.string.link); - - String noPreviewLinkUrl = post.getUrl(); - ((DataViewHolder) holder).linkTextView.setVisibility(View.VISIBLE); - String noPreviewLinkDomain = Uri.parse(noPreviewLinkUrl).getHost(); - ((DataViewHolder) holder).linkTextView.setText(noPreviewLinkDomain); - ((DataViewHolder) holder).noPreviewLinkImageView.setVisibility(View.VISIBLE); - ((DataViewHolder) holder).noPreviewLinkImageView.setOnClickListener(view -> { - Intent intent = new Intent(mContext, LinkResolverActivity.class); - Uri uri = Uri.parse(post.getUrl()); - if(uri.getScheme() == null && uri.getHost() == null) { - intent.setData(LinkResolverActivity.getRedditUriByPath(post.getUrl())); - } else { - intent.setData(uri); - } - mContext.startActivity(intent); - }); - break; - case Post.TEXT_TYPE: - ((DataViewHolder) holder).typeTextView.setText(R.string.text); - break; - } - - ((DataViewHolder) holder).upvoteButton.setOnClickListener(view -> { - if(mAccessToken == null) { - Toast.makeText(mContext, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - if(isArchived) { - Toast.makeText(mContext, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); - return; - } - - ColorFilter previousUpvoteButtonColorFilter = ((DataViewHolder) holder).upvoteButton.getColorFilter(); - ColorFilter previousDownvoteButtonColorFilter = ((DataViewHolder) holder).downvoteButton.getColorFilter(); - int previousScoreTextViewColor = ((DataViewHolder) holder).scoreTextView.getCurrentTextColor(); - - int previousVoteType = post.getVoteType(); - String newVoteType; - - ((DataViewHolder) holder).downvoteButton.clearColorFilter(); - - if(previousUpvoteButtonColorFilter == null) { - //Not upvoted before - post.setVoteType(1); - newVoteType = RedditUtils.DIR_UPVOTE; - ((DataViewHolder) holder).upvoteButton - .setColorFilter(ContextCompat.getColor(mContext, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.upvoted)); - } else { - //Upvoted before - post.setVoteType(0); - newVoteType = RedditUtils.DIR_UNVOTE; - ((DataViewHolder) holder).upvoteButton.clearColorFilter(); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); - } - - ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + post.getVoteType())); - - VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { - @Override - public void onVoteThingSuccess(int position1) { - if(newVoteType.equals(RedditUtils.DIR_UPVOTE)) { - post.setVoteType(1); - ((DataViewHolder) holder).upvoteButton - .setColorFilter(ContextCompat.getColor(mContext, R.color.upvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.upvoted)); - } else { - post.setVoteType(0); - ((DataViewHolder) holder).upvoteButton.clearColorFilter(); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); - } - - ((DataViewHolder) holder).downvoteButton.clearColorFilter(); - ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + post.getVoteType())); - - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - - @Override - public void onVoteThingFail(int position1) { - Toast.makeText(mContext, R.string.vote_failed, Toast.LENGTH_SHORT).show(); - post.setVoteType(previousVoteType); - ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + previousVoteType)); - ((DataViewHolder) holder).upvoteButton.setColorFilter(previousUpvoteButtonColorFilter); - ((DataViewHolder) holder).downvoteButton.setColorFilter(previousDownvoteButtonColorFilter); - ((DataViewHolder) holder).scoreTextView.setTextColor(previousScoreTextViewColor); - - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - }, id, newVoteType, holder.getAdapterPosition()); - }); - - ((DataViewHolder) holder).downvoteButton.setOnClickListener(view -> { - if(mAccessToken == null) { - Toast.makeText(mContext, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - if(isArchived) { - Toast.makeText(mContext, R.string.archived_post_vote_unavailable, Toast.LENGTH_SHORT).show(); - return; - } - - ColorFilter previousUpvoteButtonColorFilter = ((DataViewHolder) holder).upvoteButton.getColorFilter(); - ColorFilter previousDownvoteButtonColorFilter = ((DataViewHolder) holder).downvoteButton.getColorFilter(); - int previousScoreTextViewColor = ((DataViewHolder) holder).scoreTextView.getCurrentTextColor(); - - int previousVoteType = post.getVoteType(); - String newVoteType; - - ((DataViewHolder) holder).upvoteButton.clearColorFilter(); - - if(previousDownvoteButtonColorFilter == null) { - //Not downvoted before - post.setVoteType(-1); - newVoteType = RedditUtils.DIR_DOWNVOTE; - ((DataViewHolder) holder).downvoteButton - .setColorFilter(ContextCompat.getColor(mContext, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.downvoted)); - } else { - //Downvoted before - post.setVoteType(0); - newVoteType = RedditUtils.DIR_UNVOTE; - ((DataViewHolder) holder).downvoteButton.clearColorFilter(); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); - } - - ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + post.getVoteType())); - - VoteThing.voteThing(mOauthRetrofit, mAccessToken, new VoteThing.VoteThingListener() { - @Override - public void onVoteThingSuccess(int position1) { - if(newVoteType.equals(RedditUtils.DIR_DOWNVOTE)) { - post.setVoteType(-1); - ((DataViewHolder) holder).downvoteButton - .setColorFilter(ContextCompat.getColor(mContext, R.color.downvoted), android.graphics.PorterDuff.Mode.SRC_IN); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.downvoted)); - } else { - post.setVoteType(0); - ((DataViewHolder) holder).downvoteButton.clearColorFilter(); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); - } - - ((DataViewHolder) holder).upvoteButton.clearColorFilter(); - ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + post.getVoteType())); - - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - - @Override - public void onVoteThingFail(int position1) { - Toast.makeText(mContext, R.string.vote_failed, Toast.LENGTH_SHORT).show(); - post.setVoteType(previousVoteType); - ((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + previousVoteType)); - ((DataViewHolder) holder).upvoteButton.setColorFilter(previousUpvoteButtonColorFilter); - ((DataViewHolder) holder).downvoteButton.setColorFilter(previousDownvoteButtonColorFilter); - ((DataViewHolder) holder).scoreTextView.setTextColor(previousScoreTextViewColor); - - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - }, id, newVoteType, holder.getAdapterPosition()); - }); - - ((DataViewHolder) holder).commentButton.setOnClickListener(view -> { - if(mAccessToken == null) { - Toast.makeText(mContext, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - Intent intent = new Intent(mContext, CommentActivity.class); - intent.putExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY, post.getFullName()); - intent.putExtra(CommentActivity.EXTRA_COMMENT_PARENT_TEXT_KEY, post.getTitle()); - intent.putExtra(CommentActivity.EXTRA_IS_REPLYING_KEY, false); - intent.putExtra(CommentActivity.EXTRA_PARENT_DEPTH_KEY, 0); - mContext.startActivity(intent); - }); - - ((DataViewHolder) holder).commentsCountTextView.setText(Integer.toString(post.getnComments())); - - if(post.isSaved()) { - ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); - } else { - ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); - } - - ((DataViewHolder) holder).saveButton.setOnClickListener(view -> { - if(mAccessToken == null) { - Toast.makeText(mContext, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - if(post.isSaved()) { - ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); - SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, post.getFullName(), - new SaveThing.SaveThingListener() { - @Override - public void success() { - post.setSaved(false); - ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); - Toast.makeText(mContext, R.string.post_unsaved_success, Toast.LENGTH_SHORT).show(); - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - - @Override - public void failed() { - post.setSaved(true); - ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); - Toast.makeText(mContext, R.string.post_unsaved_failed, Toast.LENGTH_SHORT).show(); - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - }); - } else { - ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); - SaveThing.saveThing(mOauthRetrofit, mAccessToken, post.getFullName(), - new SaveThing.SaveThingListener() { - @Override - public void success() { - post.setSaved(true); - ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_24px); - Toast.makeText(mContext, R.string.post_saved_success, Toast.LENGTH_SHORT).show(); - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - - @Override - public void failed() { - post.setSaved(false); - ((DataViewHolder) holder).saveButton.setImageResource(R.drawable.ic_baseline_bookmark_border_24px); - Toast.makeText(mContext, R.string.post_saved_failed, Toast.LENGTH_SHORT).show(); - EventBus.getDefault().post(new PostUpdateEventToDetailActivity(post)); - } - }); - } - }); - - ((DataViewHolder) holder).shareButton.setOnClickListener(view -> { - try { - Intent intent = new Intent(Intent.ACTION_SEND); - intent.setType("text/plain"); - String extraText = title + "\n" + permalink; - intent.putExtra(Intent.EXTRA_TEXT, extraText); - mContext.startActivity(Intent.createChooser(intent, mContext.getString(R.string.share))); - } catch (ActivityNotFoundException e) { - Toast.makeText(mContext, R.string.no_activity_found_for_share, Toast.LENGTH_SHORT).show(); - } - }); - } - } - } - - private void loadImage(final RecyclerView.ViewHolder holder, final Post post) { - RequestBuilder imageRequestBuilder = mGlide.load(post.getPreviewUrl()).listener(new RequestListener() { - @Override - public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { - ((DataViewHolder) holder).progressBar.setVisibility(View.GONE); - ((DataViewHolder) holder).errorRelativeLayout.setVisibility(View.VISIBLE); - ((DataViewHolder)holder).errorRelativeLayout.setOnClickListener(view -> { - ((DataViewHolder) holder).progressBar.setVisibility(View.VISIBLE); - ((DataViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); - loadImage(holder, post); - }); - return false; - } - - @Override - public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { - ((DataViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); - ((DataViewHolder) holder).progressBar.setVisibility(View.GONE); - return false; - } - }); - - if((post.isNSFW() && mNeedBlurNSFW) || post.isSpoiler() && mNeedBlurSpoiler) { - imageRequestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(50, 2))) - .into(((DataViewHolder) holder).imageView); - } else { - imageRequestBuilder.into(((DataViewHolder) holder).imageView); - } - } - - @Override - public int getItemViewType(int position) { - // Reached at the end - if (hasExtraRow() && position == getItemCount() - 1) { - if (networkState.getStatus() == NetworkState.Status.LOADING) { - return VIEW_TYPE_LOADING; - } else { - return VIEW_TYPE_ERROR; - } - } else { - return VIEW_TYPE_DATA; - } - } - - @Override - public int getItemCount() { - if(hasExtraRow()) { - return super.getItemCount() + 1; - } - return super.getItemCount(); - } - - void setBlurNSFW(boolean needBlurNSFW) { - mNeedBlurNSFW = needBlurNSFW; - } - - void setBlurSpoiler(boolean needBlurSpoiler) { - mNeedBlurSpoiler = needBlurSpoiler; - } - - private boolean hasExtraRow() { - return networkState != null && networkState.getStatus() != NetworkState.Status.SUCCESS; - } - - void setNetworkState(NetworkState newNetworkState) { - NetworkState previousState = this.networkState; - boolean previousExtraRow = hasExtraRow(); - this.networkState = newNetworkState; - boolean newExtraRow = hasExtraRow(); - if (previousExtraRow != newExtraRow) { - if (previousExtraRow) { - notifyItemRemoved(super.getItemCount()); - } else { - notifyItemInserted(super.getItemCount()); - } - } else if (newExtraRow && !previousState.equals(newNetworkState)) { - notifyItemChanged(getItemCount() - 1); - } - } - - class DataViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.card_view_item_post) MaterialCardView cardView; - @BindView(R.id.icon_name_linear_layout_view_item_post) LinearLayout iconNameLinearLayout; - @BindView(R.id.icon_gif_image_view_item_post) AspectRatioGifImageView iconGifImageView; - @BindView(R.id.name_text_view_item_post) TextView nameTextView; - @BindView(R.id.stickied_post_image_view_item_post) ImageView stickiedPostImageView; - @BindView(R.id.post_time_text_view_best_item_post) TextView postTimeTextView; - @BindView(R.id.title_text_view_best_item_post) TextView titleTextView; - @BindView(R.id.type_text_view_item_post) CustomTextView typeTextView; - @BindView(R.id.gilded_image_view_item_post) ImageView gildedImageView; - @BindView(R.id.gilded_number_text_view_item_post) TextView gildedNumberTextView; - @BindView(R.id.archived_image_view_item_post) ImageView archivedImageView; - @BindView(R.id.locked_image_view_item_post) ImageView lockedImageView; - @BindView(R.id.crosspost_image_view_item_post) ImageView crosspostImageView; - @BindView(R.id.nsfw_text_view_item_post) CustomTextView nsfwTextView; - @BindView(R.id.spoiler_flair_linear_layout_item_post) LinearLayout spoilerFlairLinearLayout; - @BindView(R.id.spoiler_custom_text_view_item_post) CustomTextView spoilerTextView; - @BindView(R.id.flair_custom_text_view_item_post) CustomTextView flairTextView; - @BindView(R.id.link_text_view_item_post) TextView linkTextView; - @BindView(R.id.image_view_wrapper_item_post) RelativeLayout relativeLayout; - @BindView(R.id.progress_bar_item_post) ProgressBar progressBar; - @BindView(R.id.image_view_best_post_item) AspectRatioGifImageView imageView; - @BindView(R.id.load_image_error_relative_layout_item_post) RelativeLayout errorRelativeLayout; - @BindView(R.id.image_view_no_preview_link_item_post) ImageView noPreviewLinkImageView; - @BindView(R.id.plus_button_item_post) ImageView upvoteButton; - @BindView(R.id.score_text_view_item_post) TextView scoreTextView; - @BindView(R.id.minus_button_item_post) ImageView downvoteButton; - @BindView(R.id.comment_button_item_post) ImageView commentButton; - @BindView(R.id.comments_count_item_post) TextView commentsCountTextView; - @BindView(R.id.save_button_item_post) ImageView saveButton; - @BindView(R.id.share_button_item_post) ImageView shareButton; - - DataViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - scoreTextView.setOnClickListener(view -> { - //Do nothing in order to prevent clicking this to start ViewPostDetailActivity - }); - } - } - - class ErrorViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.error_text_view_item_footer_error) TextView errorTextView; - @BindView(R.id.retry_button_item_footer_error) Button retryButton; - - ErrorViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - errorTextView.setText(R.string.load_posts_error); - retryButton.setOnClickListener(view -> mCallback.retryLoadingMore()); - } - } - - class LoadingViewHolder extends RecyclerView.ViewHolder { - LoadingViewHolder(@NonNull View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - } - } - - @Override - public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { - if(holder instanceof DataViewHolder) { - mGlide.clear(((DataViewHolder) holder).imageView); - mGlide.clear(((DataViewHolder) holder).iconGifImageView); - ((DataViewHolder) holder).stickiedPostImageView.setVisibility(View.GONE); - ((DataViewHolder) holder).relativeLayout.setVisibility(View.GONE); - ((DataViewHolder) holder).gildedImageView.setVisibility(View.GONE); - ((DataViewHolder) holder).gildedNumberTextView.setVisibility(View.GONE); - ((DataViewHolder) holder).crosspostImageView.setVisibility(View.GONE); - ((DataViewHolder) holder).archivedImageView.setVisibility(View.GONE); - ((DataViewHolder) holder).lockedImageView.setVisibility(View.GONE); - ((DataViewHolder) holder).nsfwTextView.setVisibility(View.GONE); - ((DataViewHolder) holder).spoilerFlairLinearLayout.setVisibility(View.GONE); - ((DataViewHolder) holder).spoilerTextView.setVisibility(View.GONE); - ((DataViewHolder) holder).flairTextView.setVisibility(View.GONE); - ((DataViewHolder) holder).linkTextView.setVisibility(View.GONE); - ((DataViewHolder) holder).progressBar.setVisibility(View.GONE); - ((DataViewHolder) holder).imageView.setVisibility(View.GONE); - ((DataViewHolder) holder).errorRelativeLayout.setVisibility(View.GONE); - ((DataViewHolder) holder).noPreviewLinkImageView.setVisibility(View.GONE); - ((DataViewHolder) holder).upvoteButton.clearColorFilter(); - ((DataViewHolder) holder).scoreTextView.setTextColor(ContextCompat.getColor(mContext, R.color.defaultTextColor)); - ((DataViewHolder) holder).downvoteButton.clearColorFilter(); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostTextActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostTextActivity.java deleted file mode 100644 index 2997282c..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostTextActivity.java +++ /dev/null @@ -1,495 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.widget.Button; -import android.widget.EditText; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.core.content.ContextCompat; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.bumptech.glide.request.RequestOptions; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import com.google.android.material.snackbar.Snackbar; -import com.libRG.CustomTextView; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import pl.droidsonroids.gif.GifImageView; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class PostTextActivity extends AppCompatActivity implements FlairBottomSheetFragment.FlairSelectionCallback { - - static final String EXTRA_SUBREDDIT_NAME = "ESN"; - static final String EXTRA_CONTENT = "EC"; - - private static final String SUBREDDIT_NAME_STATE = "SNS"; - private static final String SUBREDDIT_ICON_STATE = "SIS"; - private static final String SUBREDDIT_SELECTED_STATE = "SSS"; - private static final String SUBREDDIT_IS_USER_STATE = "SIUS"; - private static final String LOAD_SUBREDDIT_ICON_STATE = "LSIS"; - private static final String IS_POSTING_STATE = "IPS"; - private static final String FLAIR_STATE = "FS"; - private static final String IS_SPOILER_STATE = "ISS"; - private static final String IS_NSFW_STATE = "INS"; - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - - private static final int SUBREDDIT_SELECTION_REQUEST_CODE = 0; - - @BindView(R.id.coordinator_layout_post_text_activity) CoordinatorLayout coordinatorLayout; - @BindView(R.id.toolbar_post_text_activity) Toolbar toolbar; - @BindView(R.id.subreddit_icon_gif_image_view_search_activity) GifImageView iconGifImageView; - @BindView(R.id.subreddit_name_text_view_search_activity) TextView subredditNameTextView; - @BindView(R.id.rules_button_post_text_activity) Button rulesButton; - @BindView(R.id.flair_custom_text_view_post_text_activity) CustomTextView flairTextView; - @BindView(R.id.spoiler_custom_text_view_post_text_activity) CustomTextView spoilerTextView; - @BindView(R.id.nsfw_custom_text_view_post_text_activity) CustomTextView nsfwTextView; - @BindView(R.id.post_title_edit_text_post_text_activity) EditText titleEditText; - @BindView(R.id.post_text_content_edit_text_post_text_activity) EditText contentEditText; - - private boolean mNullAccessToken = false; - private String mAccessToken; - private String iconUrl; - private String subredditName; - private boolean subredditSelected = false; - private boolean subredditIsUser; - private boolean loadSubredditIconSuccessful = true; - private boolean isPosting; - - private Flair flair; - private boolean isSpoiler = false; - private boolean isNSFW = false; - - private Menu mMemu; - private RequestManager mGlide; - private FlairBottomSheetFragment flairSelectionBottomSheetFragment; - private Snackbar mPostingSnackbar; - - @Inject - @Named("no_oauth") - Retrofit mRetrofit; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_post_text); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - Window window = getWindow(); - if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - mGlide = Glide.with(this); - - mPostingSnackbar = Snackbar.make(coordinatorLayout, R.string.posting, Snackbar.LENGTH_INDEFINITE); - - if(savedInstanceState != null) { - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - - if(!mNullAccessToken && mAccessToken == null) { - getCurrentAccount(); - } - - subredditName = savedInstanceState.getString(SUBREDDIT_NAME_STATE); - iconUrl = savedInstanceState.getString(SUBREDDIT_ICON_STATE); - subredditSelected = savedInstanceState.getBoolean(SUBREDDIT_SELECTED_STATE); - subredditIsUser = savedInstanceState.getBoolean(SUBREDDIT_IS_USER_STATE); - loadSubredditIconSuccessful = savedInstanceState.getBoolean(LOAD_SUBREDDIT_ICON_STATE); - isPosting = savedInstanceState.getBoolean(IS_POSTING_STATE); - flair = savedInstanceState.getParcelable(FLAIR_STATE); - isSpoiler = savedInstanceState.getBoolean(IS_SPOILER_STATE); - isNSFW = savedInstanceState.getBoolean(IS_NSFW_STATE); - - if(subredditName != null) { - subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); - subredditNameTextView.setText(subredditName); - flairTextView.setVisibility(View.VISIBLE); - if(!loadSubredditIconSuccessful) { - loadSubredditIcon(); - } - } - displaySubredditIcon(); - - if(isPosting) { - mPostingSnackbar.show(); - } - - if(flair != null) { - flairTextView.setText(flair.getText()); - flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - } - if(isSpoiler) { - spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - } - if(isNSFW) { - nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); - } - } else { - getCurrentAccount(); - - isPosting = false; - - if(getIntent().hasExtra(EXTRA_SUBREDDIT_NAME)) { - loadSubredditIconSuccessful = false; - subredditName = getIntent().getStringExtra(EXTRA_SUBREDDIT_NAME); - subredditSelected = true; - subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); - subredditNameTextView.setText(subredditName); - flairTextView.setVisibility(View.VISIBLE); - loadSubredditIcon(); - } else { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(iconGifImageView); - } - - String text = getIntent().getStringExtra(EXTRA_CONTENT); - if(text != null) { - contentEditText.setText(text); - } - } - - iconGifImageView.setOnClickListener(view -> { - Intent intent = new Intent(this, SubredditSelectionActivity.class); - startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); - }); - - subredditNameTextView.setOnClickListener(view -> { - Intent intent = new Intent(this, SubredditSelectionActivity.class); - startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); - }); - - rulesButton.setOnClickListener(view -> { - if(subredditName == null) { - Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); - } else { - Intent intent = new Intent(this, RulesActivity.class); - if(subredditIsUser) { - intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, "u_" + subredditName); - } else { - intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, subredditName); - } - startActivity(intent); - } - }); - - flairTextView.setOnClickListener(view -> { - if(flair == null) { - flairSelectionBottomSheetFragment = new FlairBottomSheetFragment(); - Bundle bundle = new Bundle(); - bundle.putString(FlairBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - if(subredditIsUser) { - bundle.putString(FlairBottomSheetFragment.EXTRA_SUBREDDIT_NAME, "u_" + subredditName); - } else { - bundle.putString(FlairBottomSheetFragment.EXTRA_SUBREDDIT_NAME, subredditName); - } - flairSelectionBottomSheetFragment.setArguments(bundle); - flairSelectionBottomSheetFragment.show(getSupportFragmentManager(), flairSelectionBottomSheetFragment.getTag()); - } else { - flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - flairTextView.setText(getString(R.string.flair)); - flair = null; - } - }); - - spoilerTextView.setOnClickListener(view -> { - if(!isSpoiler) { - spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - isSpoiler = true; - } else { - spoilerTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - isSpoiler = false; - } - }); - - nsfwTextView.setOnClickListener(view -> { - if(!isNSFW) { - nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); - isNSFW = true; - } else { - nsfwTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - isNSFW = false; - } - }); - } - - private void getCurrentAccount() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - } - }).execute(); - } - - private void displaySubredditIcon() { - if(iconUrl != null && !iconUrl.equals("")) { - mGlide.load(iconUrl) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(iconGifImageView); - } else { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(iconGifImageView); - } - } - - private void loadSubredditIcon() { - new LoadSubredditIconAsyncTask(mRedditDataRoomDatabase, subredditName, mRetrofit, iconImageUrl -> { - iconUrl = iconImageUrl; - displaySubredditIcon(); - loadSubredditIconSuccessful = true; - }).execute(); - } - - private void promptAlertDialog(int titleResId, int messageResId) { - new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme) - .setTitle(titleResId) - .setMessage(messageResId) - .setPositiveButton(R.string.yes, (dialogInterface, i) - -> finish()) - .setNegativeButton(R.string.no, null) - .show(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.post_text_activity, menu); - mMemu = menu; - if(isPosting) { - mMemu.findItem(R.id.action_send_post_text_activity).setEnabled(false); - mMemu.findItem(R.id.action_send_post_text_activity).getIcon().setAlpha(130); - } - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - if(isPosting) { - promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); - return true; - } else { - if(!titleEditText.getText().toString().equals("") || !contentEditText.getText().toString().equals("")) { - promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); - return true; - } - } - finish(); - return true; - case R.id.action_send_post_text_activity: - if(!subredditSelected) { - Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); - return true; - } - - if(titleEditText.getText() == null || titleEditText.getText().toString().equals("")) { - Snackbar.make(coordinatorLayout, R.string.title_required, Snackbar.LENGTH_SHORT).show(); - return true; - } - - isPosting = true; - - item.setEnabled(false); - item.getIcon().setAlpha(130); - - mPostingSnackbar.show(); - - String subredditName; - if(subredditIsUser) { - subredditName = "u_" + subredditNameTextView.getText().toString(); - } else { - subredditName = subredditNameTextView.getText().toString(); - } - - Intent intent = new Intent(this, SubmitPostService.class); - intent.putExtra(SubmitPostService.EXTRA_ACCESS_TOKEN, mAccessToken); - intent.putExtra(SubmitPostService.EXTRA_SUBREDDIT_NAME, subredditName); - intent.putExtra(SubmitPostService.EXTRA_TITLE, titleEditText.getText().toString()); - intent.putExtra(SubmitPostService.EXTRA_CONTENT, contentEditText.getText().toString()); - intent.putExtra(SubmitPostService.EXTRA_KIND, RedditUtils.KIND_SELF); - intent.putExtra(SubmitPostService.EXTRA_FLAIR, flair); - intent.putExtra(SubmitPostService.EXTRA_IS_SPOILER, isSpoiler); - intent.putExtra(SubmitPostService.EXTRA_IS_NSFW, isNSFW); - intent.putExtra(SubmitPostService.EXTRA_POST_TYPE, SubmitPostService.EXTRA_POST_TEXT_OR_LINK); - startService(intent); - - return true; - } - - return false; - } - - @Override - public void onBackPressed() { - if(isPosting) { - promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); - } else { - if(!titleEditText.getText().toString().equals("") || !contentEditText.getText().toString().equals("")) { - promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); - } else { - finish(); - } - } - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putString(SUBREDDIT_NAME_STATE, subredditName); - outState.putString(SUBREDDIT_ICON_STATE, iconUrl); - outState.putBoolean(SUBREDDIT_SELECTED_STATE, subredditSelected); - outState.putBoolean(SUBREDDIT_IS_USER_STATE, subredditIsUser); - outState.putBoolean(LOAD_SUBREDDIT_ICON_STATE, loadSubredditIconSuccessful); - outState.putBoolean(IS_POSTING_STATE, isPosting); - outState.putParcelable(FLAIR_STATE, flair); - outState.putBoolean(IS_SPOILER_STATE, isSpoiler); - outState.putBoolean(IS_NSFW_STATE, isNSFW); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if(requestCode == SUBREDDIT_SELECTION_REQUEST_CODE) { - if(resultCode == RESULT_OK) { - subredditName = data.getExtras().getString(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_NAME); - iconUrl = data.getExtras().getString(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_ICON_URL); - subredditSelected = true; - subredditIsUser = data.getExtras().getBoolean(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_IS_USER); - - subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); - subredditNameTextView.setText(subredditName); - displaySubredditIcon(); - - flairTextView.setVisibility(View.VISIBLE); - flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - flairTextView.setText(getString(R.string.flair)); - flair = null; - } - } - } - - @Override - protected void onDestroy() { - EventBus.getDefault().unregister(this); - super.onDestroy(); - } - - @Override - public void flairSelected(Flair flair) { - this.flair = flair; - flairTextView.setText(flair.getText()); - flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } - - @Subscribe - public void onSubmitTextPostEvent(SubmitTextOrLinkPostEvent submitTextOrLinkPostEvent) { - isPosting = false; - mPostingSnackbar.dismiss(); - if(submitTextOrLinkPostEvent.postSuccess) { - Intent intent = new Intent(PostTextActivity.this, ViewPostDetailActivity.class); - intent.putExtra(ViewPostDetailActivity.EXTRA_POST_DATA, submitTextOrLinkPostEvent.post); - startActivity(intent); - finish(); - } else { - mMemu.findItem(R.id.action_send_post_text_activity).setEnabled(true); - mMemu.findItem(R.id.action_send_post_text_activity).getIcon().setAlpha(255); - if(submitTextOrLinkPostEvent.errorMessage == null) { - Snackbar.make(coordinatorLayout, R.string.post_failed, Snackbar.LENGTH_SHORT).show(); - } else { - Snackbar.make(coordinatorLayout, submitTextOrLinkPostEvent.errorMessage.substring(0, 1).toUpperCase() - + submitTextOrLinkPostEvent.errorMessage.substring(1), Snackbar.LENGTH_SHORT).show(); - } - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostTypeBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostTypeBottomSheetFragment.java deleted file mode 100644 index 338821c0..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostTypeBottomSheetFragment.java +++ /dev/null @@ -1,81 +0,0 @@ -package ml.docilealligator.infinityforreddit; - - -import android.app.Activity; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; - -import androidx.fragment.app.Fragment; - -import com.deishelon.roundedbottomsheet.RoundedBottomSheetDialogFragment; - -import butterknife.BindView; -import butterknife.ButterKnife; - - -/** - * A simple {@link Fragment} subclass. - */ -public class PostTypeBottomSheetFragment extends RoundedBottomSheetDialogFragment { - - interface PostTypeSelectionCallback { - void postTypeSelected(int postType); - } - - static final int TYPE_TEXT = 0; - static final int TYPE_LINK = 1; - static final int TYPE_IMAGE = 2; - static final int TYPE_VIDEO = 3; - - @BindView(R.id.text_type_linear_layout_post_type_bottom_sheet_fragment) LinearLayout textTypeLinearLayout; - @BindView(R.id.link_type_linear_layout_post_type_bottom_sheet_fragment) LinearLayout linkTypeLinearLayout; - @BindView(R.id.image_type_linear_layout_post_type_bottom_sheet_fragment) LinearLayout imageTypeLinearLayout; - @BindView(R.id.video_type_linear_layout_post_type_bottom_sheet_fragment) LinearLayout videoTypeLinearLayout; - - public PostTypeBottomSheetFragment() { - // Required empty public constructor - } - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_post_type_bottom_sheet, container, false); - ButterKnife.bind(this, rootView); - - Activity activity = getActivity(); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O - && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - - textTypeLinearLayout.setOnClickListener(view -> { - ((PostTypeSelectionCallback) activity).postTypeSelected(TYPE_TEXT); - dismiss(); - }); - - linkTypeLinearLayout.setOnClickListener(view -> { - ((PostTypeSelectionCallback) activity).postTypeSelected(TYPE_LINK); - dismiss(); - }); - - imageTypeLinearLayout.setOnClickListener(view -> { - ((PostTypeSelectionCallback) activity).postTypeSelected(TYPE_IMAGE); - dismiss(); - }); - - videoTypeLinearLayout.setOnClickListener(view -> { - ((PostTypeSelectionCallback) activity).postTypeSelected(TYPE_VIDEO); - dismiss(); - }); - - return rootView; - } - -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostUpdateEventToDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostUpdateEventToDetailActivity.java deleted file mode 100644 index 4646ab84..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostUpdateEventToDetailActivity.java +++ /dev/null @@ -1,9 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -public class PostUpdateEventToDetailActivity { - public final Post post; - - public PostUpdateEventToDetailActivity(Post post) { - this.post = post; - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostUpdateEventToPostList.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostUpdateEventToPostList.java deleted file mode 100644 index 937ab92b..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostUpdateEventToPostList.java +++ /dev/null @@ -1,11 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -public class PostUpdateEventToPostList { - public final Post post; - public final int positionInList; - - public PostUpdateEventToPostList(Post post, int positionInList) { - this.post = post; - this.positionInList = positionInList; - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostVideoActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostVideoActivity.java deleted file mode 100644 index df0b5f25..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostVideoActivity.java +++ /dev/null @@ -1,620 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.provider.MediaStore; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.widget.Button; -import android.widget.EditText; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.constraintlayout.widget.ConstraintLayout; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.core.content.ContextCompat; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.bumptech.glide.request.RequestOptions; -import com.google.android.exoplayer2.ExoPlayerFactory; -import com.google.android.exoplayer2.Player; -import com.google.android.exoplayer2.SimpleExoPlayer; -import com.google.android.exoplayer2.source.ExtractorMediaSource; -import com.google.android.exoplayer2.ui.PlayerView; -import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; -import com.google.android.exoplayer2.util.Util; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import com.google.android.material.floatingactionbutton.FloatingActionButton; -import com.google.android.material.snackbar.Snackbar; -import com.libRG.CustomTextView; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import pl.droidsonroids.gif.GifImageView; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class PostVideoActivity extends AppCompatActivity implements FlairBottomSheetFragment.FlairSelectionCallback { - - static final String EXTRA_SUBREDDIT_NAME = "ESN"; - - private static final String SUBREDDIT_NAME_STATE = "SNS"; - private static final String SUBREDDIT_ICON_STATE = "SIS"; - private static final String SUBREDDIT_SELECTED_STATE = "SSS"; - private static final String SUBREDDIT_IS_USER_STATE = "SIUS"; - private static final String VIDEO_URI_STATE = "IUS"; - private static final String LOAD_SUBREDDIT_ICON_STATE = "LSIS"; - private static final String IS_POSTING_STATE = "IPS"; - private static final String FLAIR_STATE = "FS"; - private static final String IS_SPOILER_STATE = "ISS"; - private static final String IS_NSFW_STATE = "INS"; - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - private static final String ACCOUNT_NAME_STATE = "ANS"; - - private static final int SUBREDDIT_SELECTION_REQUEST_CODE = 0; - private static final int PICK_VIDEO_REQUEST_CODE = 1; - private static final int CAPTURE_VIDEO_REQUEST_CODE = 2; - - @BindView(R.id.coordinator_layout_post_video_activity) CoordinatorLayout coordinatorLayout; - @BindView(R.id.toolbar_post_video_activity) Toolbar toolbar; - @BindView(R.id.subreddit_icon_gif_image_view_post_video_activity) GifImageView iconGifImageView; - @BindView(R.id.subreddit_name_text_view_post_video_activity) TextView subredditNameTextView; - @BindView(R.id.rules_button_post_video_activity) Button rulesButton; - @BindView(R.id.flair_custom_text_view_post_video_activity) CustomTextView flairTextView; - @BindView(R.id.spoiler_custom_text_view_post_video_activity) CustomTextView spoilerTextView; - @BindView(R.id.nsfw_custom_text_view_post_video_activity) CustomTextView nsfwTextView; - @BindView(R.id.post_title_edit_text_post_video_activity) EditText titleEditText; - @BindView(R.id.select_video_constraint_layout_post_video_activity) ConstraintLayout constraintLayout; - @BindView(R.id.capture_fab_post_video_activity) FloatingActionButton captureFab; - @BindView(R.id.select_from_library_fab_post_video_activity) FloatingActionButton selectFromLibraryFab; - @BindView(R.id.select_again_text_view_post_video_activity) TextView selectAgainTextView; - @BindView(R.id.player_view_post_video_activity) PlayerView videoPlayerView; - - private boolean mNullAccessToken = false; - private String mAccessToken; - private String mAccountName; - private String iconUrl; - private String subredditName; - private boolean subredditSelected = false; - private boolean subredditIsUser; - private Uri videoUri; - private boolean loadSubredditIconSuccessful = true; - private boolean isPosting; - private boolean wasPlaying; - - private Flair flair; - private boolean isSpoiler = false; - private boolean isNSFW = false; - - private Menu mMemu; - private RequestManager mGlide; - private FlairBottomSheetFragment mFlairSelectionBottomSheetFragment; - private Snackbar mPostingSnackbar; - - private DataSource.Factory dataSourceFactory; - private SimpleExoPlayer player; - - @Inject - @Named("no_oauth") - Retrofit mRetrofit; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - @Named("upload_media") - Retrofit mUploadMediaRetrofit; - - @Inject - @Named("upload_video") - Retrofit mUploadVideoRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_post_video); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - Window window = getWindow(); - if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - mGlide = Glide.with(this); - - player = ExoPlayerFactory.newSimpleInstance(this); - videoPlayerView.setPlayer(player); - dataSourceFactory = new DefaultDataSourceFactory(this, - Util.getUserAgent(this, "Infinity")); - player.setRepeatMode(Player.REPEAT_MODE_ALL); - - mPostingSnackbar = Snackbar.make(coordinatorLayout, R.string.posting, Snackbar.LENGTH_INDEFINITE); - - if(savedInstanceState != null) { - subredditName = savedInstanceState.getString(SUBREDDIT_NAME_STATE); - iconUrl = savedInstanceState.getString(SUBREDDIT_ICON_STATE); - subredditSelected = savedInstanceState.getBoolean(SUBREDDIT_SELECTED_STATE); - subredditIsUser = savedInstanceState.getBoolean(SUBREDDIT_IS_USER_STATE); - loadSubredditIconSuccessful = savedInstanceState.getBoolean(LOAD_SUBREDDIT_ICON_STATE); - isPosting = savedInstanceState.getBoolean(IS_POSTING_STATE); - flair = savedInstanceState.getParcelable(FLAIR_STATE); - isSpoiler = savedInstanceState.getBoolean(IS_SPOILER_STATE); - isNSFW = savedInstanceState.getBoolean(IS_NSFW_STATE); - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); - - if(!mNullAccessToken && mAccessToken == null) { - getCurrentAccount(); - } - - if(savedInstanceState.getString(VIDEO_URI_STATE) != null) { - videoUri = Uri.parse(savedInstanceState.getString(VIDEO_URI_STATE)); - loadVideo(); - } - - if(subredditName != null) { - subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); - subredditNameTextView.setText(subredditName); - flairTextView.setVisibility(View.VISIBLE); - if(!loadSubredditIconSuccessful) { - loadSubredditIcon(); - } - } - displaySubredditIcon(); - - if(isPosting) { - mPostingSnackbar.show(); - } - - if(flair != null) { - flairTextView.setText(flair.getText()); - flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - } - if(isSpoiler) { - spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - } - if(isNSFW) { - nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); - } - } else { - getCurrentAccount(); - - isPosting = false; - - if(getIntent().hasExtra(EXTRA_SUBREDDIT_NAME)) { - loadSubredditIconSuccessful = false; - subredditName = getIntent().getStringExtra(EXTRA_SUBREDDIT_NAME); - subredditSelected = true; - subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); - subredditNameTextView.setText(subredditName); - loadSubredditIcon(); - } else { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(iconGifImageView); - } - - videoUri = getIntent().getData(); - if(videoUri != null) { - loadVideo(); - } - } - - iconGifImageView.setOnClickListener(view -> { - Intent intent = new Intent(this, SubredditSelectionActivity.class); - startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); - }); - - subredditNameTextView.setOnClickListener(view -> { - Intent intent = new Intent(this, SubredditSelectionActivity.class); - startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); - }); - - rulesButton.setOnClickListener(view -> { - if(subredditName == null) { - Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); - } else { - Intent intent = new Intent(this, RulesActivity.class); - if(subredditIsUser) { - intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, "u_" + subredditName); - } else { - intent.putExtra(RulesActivity.EXTRA_SUBREDDIT_NAME, subredditName); - } - startActivity(intent); - } - }); - - flairTextView.setOnClickListener(view -> { - if(flair == null) { - mFlairSelectionBottomSheetFragment = new FlairBottomSheetFragment(); - Bundle bundle = new Bundle(); - bundle.putString(FlairBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - bundle.putString(FlairBottomSheetFragment.EXTRA_SUBREDDIT_NAME, subredditName); - mFlairSelectionBottomSheetFragment.setArguments(bundle); - mFlairSelectionBottomSheetFragment.show(getSupportFragmentManager(), mFlairSelectionBottomSheetFragment.getTag()); - } else { - flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - flairTextView.setText(getString(R.string.flair)); - flair = null; - } - }); - - spoilerTextView.setOnClickListener(view -> { - if(!isSpoiler) { - spoilerTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - isSpoiler = true; - } else { - spoilerTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - isSpoiler = false; - } - }); - - nsfwTextView.setOnClickListener(view -> { - if(!isNSFW) { - nsfwTextView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); - isNSFW = true; - } else { - nsfwTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - isNSFW = false; - } - }); - - captureFab.setOnClickListener(view -> { - Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); - if (takeVideoIntent.resolveActivity(getPackageManager()) != null) { - startActivityForResult(takeVideoIntent, CAPTURE_VIDEO_REQUEST_CODE); - } - }); - - selectFromLibraryFab.setOnClickListener(view -> { - Intent intent = new Intent(); - intent.setType("video/*"); - intent.setAction(Intent.ACTION_GET_CONTENT); - startActivityForResult(Intent.createChooser(intent,getResources().getString(R.string.select_from_gallery)), PICK_VIDEO_REQUEST_CODE); - }); - - selectAgainTextView.setOnClickListener(view -> { - wasPlaying = false; - player.setPlayWhenReady(false); - videoUri = null; - videoPlayerView.setVisibility(View.GONE); - selectAgainTextView.setVisibility(View.GONE); - constraintLayout.setVisibility(View.VISIBLE); - }); - } - - private void getCurrentAccount() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - } - }).execute(); - } - - private void loadVideo() { - constraintLayout.setVisibility(View.GONE); - selectAgainTextView.setVisibility(View.VISIBLE); - videoPlayerView.setVisibility(View.VISIBLE); - player.prepare(new ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(videoUri)); - player.setPlayWhenReady(true); - wasPlaying = true; - } - - private void displaySubredditIcon() { - if(iconUrl != null && !iconUrl.equals("")) { - mGlide.load(iconUrl) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(iconGifImageView); - } else { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(iconGifImageView); - } - } - - private void loadSubredditIcon() { - new LoadSubredditIconAsyncTask(mRedditDataRoomDatabase, subredditName, mRetrofit, iconImageUrl -> { - iconUrl = iconImageUrl; - displaySubredditIcon(); - loadSubredditIconSuccessful = true; - }).execute(); - } - - private void promptAlertDialog(int titleResId, int messageResId) { - new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme) - .setTitle(titleResId) - .setMessage(messageResId) - .setPositiveButton(R.string.yes, (dialogInterface, i) -> finish()) - .setNegativeButton(R.string.no, null) - .show(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.post_video_activity, menu); - mMemu = menu; - if(isPosting) { - mMemu.findItem(R.id.action_send_post_video_activity).setEnabled(false); - mMemu.findItem(R.id.action_send_post_video_activity).getIcon().setAlpha(130); - } - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - if(isPosting) { - promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); - return true; - } else { - if(!titleEditText.getText().toString().equals("") || videoUri != null) { - promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); - return true; - } - } - finish(); - return true; - case R.id.action_send_post_video_activity: - if(!subredditSelected) { - Snackbar.make(coordinatorLayout, R.string.select_a_subreddit, Snackbar.LENGTH_SHORT).show(); - return true; - } - - if(titleEditText.getText() == null || titleEditText.getText().toString().equals("")) { - Snackbar.make(coordinatorLayout, R.string.title_required, Snackbar.LENGTH_SHORT).show(); - return true; - } - - if(videoUri == null) { - Snackbar.make(coordinatorLayout, R.string.select_an_image, Snackbar.LENGTH_SHORT).show(); - return true; - } - - isPosting = true; - - item.setEnabled(false); - item.getIcon().setAlpha(130); - - mPostingSnackbar.show(); - - String subredditName; - if(subredditIsUser) { - subredditName = "u_" + subredditNameTextView.getText().toString(); - } else { - subredditName = subredditNameTextView.getText().toString(); - } - - Intent intent = new Intent(this, SubmitPostService.class); - intent.setData(videoUri); - intent.putExtra(SubmitPostService.EXTRA_ACCESS_TOKEN, mAccessToken); - intent.putExtra(SubmitPostService.EXTRA_SUBREDDIT_NAME, subredditName); - intent.putExtra(SubmitPostService.EXTRA_TITLE, titleEditText.getText().toString()); - intent.putExtra(SubmitPostService.EXTRA_FLAIR, flair); - intent.putExtra(SubmitPostService.EXTRA_IS_SPOILER, isSpoiler); - intent.putExtra(SubmitPostService.EXTRA_IS_NSFW, isNSFW); - intent.putExtra(SubmitPostService.EXTRA_POST_TYPE, SubmitPostService.EXTRA_POST_TYPE_VIDEO); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - startForegroundService(intent); - } else { - startService(intent); - } - - return true; - } - - return false; - } - - @Override - public void onBackPressed() { - if(isPosting) { - promptAlertDialog(R.string.exit_when_submit_post, R.string.exit_when_submit_post_detail); - } else { - if(!titleEditText.getText().toString().equals("") || videoUri != null) { - promptAlertDialog(R.string.discard_post, R.string.discard_post_detail); - } else { - finish(); - } - } - } - - @Override - protected void onStart() { - super.onStart(); - if(wasPlaying) { - player.setPlayWhenReady(true); - } - } - - @Override - protected void onStop() { - super.onStop(); - player.setPlayWhenReady(false); - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putString(SUBREDDIT_NAME_STATE, subredditName); - outState.putString(SUBREDDIT_ICON_STATE, iconUrl); - outState.putBoolean(SUBREDDIT_SELECTED_STATE, subredditSelected); - outState.putBoolean(SUBREDDIT_IS_USER_STATE, subredditIsUser); - if(videoUri != null) { - outState.putString(VIDEO_URI_STATE, videoUri.toString()); - } - outState.putBoolean(LOAD_SUBREDDIT_ICON_STATE, loadSubredditIconSuccessful); - outState.putBoolean(IS_POSTING_STATE, isPosting); - outState.putParcelable(FLAIR_STATE, flair); - outState.putBoolean(IS_SPOILER_STATE, isSpoiler); - outState.putBoolean(IS_NSFW_STATE, isNSFW); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - outState.putString(ACCOUNT_NAME_STATE, mAccountName); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if(requestCode == SUBREDDIT_SELECTION_REQUEST_CODE) { - if(resultCode == RESULT_OK) { - if(data != null) { - subredditName = data.getStringExtra(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_NAME); - iconUrl = data.getStringExtra(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_ICON_URL); - subredditSelected = true; - subredditIsUser = data.getBooleanExtra(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_IS_USER, false); - - subredditNameTextView.setTextColor(getResources().getColor(R.color.primaryTextColor)); - subredditNameTextView.setText(subredditName); - displaySubredditIcon(); - - flairTextView.setVisibility(View.VISIBLE); - flairTextView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); - flairTextView.setText(getString(R.string.flair)); - flair = null; - } - } - } else if(requestCode == PICK_VIDEO_REQUEST_CODE) { - if(resultCode == RESULT_OK) { - if(data == null) { - Snackbar.make(coordinatorLayout, R.string.error_getting_video, Snackbar.LENGTH_SHORT).show(); - return; - } - - videoUri = data.getData(); - loadVideo(); - } - } else if (requestCode == CAPTURE_VIDEO_REQUEST_CODE) { - if(resultCode == RESULT_OK) { - if(data != null && data.getData() != null) { - videoUri = data.getData(); - loadVideo(); - } else { - Snackbar.make(coordinatorLayout, R.string.error_getting_video, Snackbar.LENGTH_SHORT).show(); - } - } - } - } - - @Override - protected void onDestroy() { - EventBus.getDefault().unregister(this); - super.onDestroy(); - player.release(); - } - - @Override - public void flairSelected(Flair flair) { - this.flair = flair; - flairTextView.setText(flair.getText()); - flairTextView.setBackgroundColor(getResources().getColor(R.color.backgroundColorPrimaryDark)); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } - - @Subscribe - public void onSubmitVideoPostEvent(SubmitVideoPostEvent submitVideoPostEvent) { - isPosting = false; - mPostingSnackbar.dismiss(); - mMemu.findItem(R.id.action_send_post_video_activity).setEnabled(true); - mMemu.findItem(R.id.action_send_post_video_activity).getIcon().setAlpha(255); - - if(submitVideoPostEvent.postSuccess) { - Intent intent = new Intent(this, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, - mAccountName); - startActivity(intent); - finish(); - } else if(submitVideoPostEvent.errorProcessingVideo) { - Snackbar.make(coordinatorLayout, R.string.error_processing_video, Snackbar.LENGTH_SHORT).show(); - } else { - if (submitVideoPostEvent.errorMessage == null || submitVideoPostEvent.errorMessage.equals("")) { - Snackbar.make(coordinatorLayout, R.string.post_failed, Snackbar.LENGTH_SHORT).show(); - } else { - Snackbar.make(coordinatorLayout, submitVideoPostEvent.errorMessage.substring(0, 1).toUpperCase() - + submitVideoPostEvent.errorMessage.substring(1), Snackbar.LENGTH_SHORT).show(); - } - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostViewModel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostViewModel.java index 9340e20b..c2df1797 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostViewModel.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PostViewModel.java @@ -1,7 +1,5 @@ package ml.docilealligator.infinityforreddit; -import android.util.Log; - import androidx.annotation.NonNull; import androidx.core.util.Pair; import androidx.lifecycle.LiveData; @@ -60,7 +58,6 @@ public class PostViewModel extends ViewModel { public PostViewModel(Retrofit retrofit, String accessToken, Locale locale, String subredditName, int postType, String sortType, int filter, boolean nsfw) { - Log.i("asfdasdf", "viewmodel: " + sortType); postDataSourceFactory = new PostDataSourceFactory(retrofit, accessToken, locale, subredditName, postType, sortType, filter, nsfw); @@ -152,35 +149,35 @@ public class PostViewModel extends ViewModel { }); } - LiveData> getPosts() { + public LiveData> getPosts() { return posts; } - LiveData getPaginationNetworkState() { + public LiveData getPaginationNetworkState() { return paginationNetworkState; } - LiveData getInitialLoadingState() { + public LiveData getInitialLoadingState() { return initialLoadingState; } - LiveData hasPost() { + public LiveData hasPost() { return hasPostLiveData; } - void refresh() { + public void refresh() { postDataSourceFactory.getPostDataSource().invalidate(); } - void retryLoadingMore() { + public void retryLoadingMore() { postDataSourceFactory.getPostDataSource().retryLoadingMore(); } - void changeSortType(String sortType) { + public void changeSortType(String sortType) { sortTypeLiveData.postValue(sortType); } - void changeNSFW(boolean nsfw) { + public void changeNSFW(boolean nsfw) { nsfwLiveData.postValue(nsfw); } @@ -209,7 +206,6 @@ public class PostViewModel extends ViewModel { public Factory(Retrofit retrofit, String accessToken, Locale locale, String subredditName, int postType, String sortType, int filter, boolean nsfw) { - Log.i("asfdasdf", "viewmodel factory: " + sortType); this.retrofit = retrofit; this.accessToken = accessToken; this.locale = locale; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java index 7fcb5088..93b5d4e1 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java @@ -26,6 +26,8 @@ import javax.inject.Inject; import javax.inject.Named; import ml.docilealligator.infinityforreddit.Account.Account; +import ml.docilealligator.infinityforreddit.Activity.LinkResolverActivity; +import ml.docilealligator.infinityforreddit.Activity.ViewMessageActivity; import retrofit2.Call; import retrofit2.Response; import retrofit2.Retrofit; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ReadMessage.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ReadMessage.java index 900fb7eb..ce6c9ff7 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ReadMessage.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ReadMessage.java @@ -10,14 +10,14 @@ import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; -class ReadMessage { - interface ReadMessageListener { +public class ReadMessage { + public interface ReadMessageListener { void readSuccess(); void readFailed(); } - static void readMessage(Retrofit oauthRetrofit, String accessToken, String commaSeparatedFullnames, - ReadMessageListener readMessageListener) { + public static void readMessage(Retrofit oauthRetrofit, String accessToken, String commaSeparatedFullnames, + ReadMessageListener readMessageListener) { Map params = new HashMap<>(); params.put(RedditUtils.ID_KEY, commaSeparatedFullnames); oauthRetrofit.create(RedditAPI.class).readMessage(RedditUtils.getOAuthHeader(accessToken), params) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditUtils.java index 5279f97b..6facdfb3 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditUtils.java @@ -13,73 +13,73 @@ import okhttp3.RequestBody; */ public class RedditUtils { - static final String OAUTH_URL ="https://www.reddit.com/api/v1/authorize.compact"; - static final String OAUTH_API_BASE_URI = "https://oauth.reddit.com"; - static final String API_BASE_URI = "https://www.reddit.com"; - static final String API_UPLOAD_MEDIA_URI = "https://reddit-uploaded-media.s3-accelerate.amazonaws.com"; - static final String API_UPLOAD_VIDEO_URI = "https://reddit-uploaded-video.s3-accelerate.amazonaws.com"; - - static final String CLIENT_ID_KEY = "client_id"; - static final String CLIENT_ID = ""; - static final String RESPONSE_TYPE_KEY = "response_type"; - static final String RESPONSE_TYPE = "code"; - static final String STATE_KEY = "state"; - static final String STATE = ""; - static final String REDIRECT_URI_KEY = "redirect_uri"; - static final String REDIRECT_URI = ""; - static final String DURATION_KEY = "duration"; - static final String DURATION = "permanent"; - static final String SCOPE_KEY = "scope"; - static final String SCOPE = "identity edit flair history modconfig modflair modlog modposts modwiki mysubreddits privatemessages read report save submit subscribe vote wikiedit wikiread"; - static final String ACCESS_TOKEN_KEY = "access_token"; - - static final String AUTHORIZATION_KEY = "Authorization"; - static final String AUTHORIZATION_BASE = "bearer "; - static final String USER_AGENT_KEY = "User-Agent"; - static final String USER_AGENT = ""; - - static final String GRANT_TYPE_KEY = "grant_type"; - static final String GRANT_TYPE_REFRESH_TOKEN = "refresh_token"; - static final String REFRESH_TOKEN_KEY = "refresh_token"; - - static final String DIR_KEY = "dir"; - static final String ID_KEY = "id"; - static final String RANK_KEY = "rank"; - static final String DIR_UPVOTE = "1"; - static final String DIR_UNVOTE = "0"; - static final String DIR_DOWNVOTE = "-1"; - static final String RANK = "10"; - - static final String ACTION_KEY = "action"; - static final String SR_NAME_KEY = "sr_name"; - - static final String API_TYPE_KEY = "api_type"; - static final String API_TYPE_JSON = "json"; - static final String RETURN_RTJSON_KEY = "return_rtjson"; - static final String TEXT_KEY = "text"; - static final String URL_KEY = "url"; - static final String VIDEO_POSTER_URL_KEY = "video_poster_url"; - static final String THING_ID_KEY = "thing_id"; - - static final String SR_KEY = "sr"; - static final String TITLE_KEY = "title"; - static final String FLAIR_TEXT_KEY = "flair_text"; - static final String SPOILER_KEY = "spoiler"; - static final String NSFW_KEY = "nsfw"; - static final String KIND_KEY = "kind"; - static final String KIND_SELF = "self"; - static final String KIND_LINK = "link"; - static final String KIND_IMAGE = "image"; - static final String KIND_VIDEO = "video"; - static final String KIND_VIDEOGIF = "videogif"; - - static final String FILEPATH_KEY = "filepath"; - static final String MIMETYPE_KEY = "mimetype"; - - static final String LINK_KEY = "link"; - static final String FLAIR_TEMPLATE_ID_KEY = "flair_template_id"; - - static Map getHttpBasicAuthHeader() { + public static final String OAUTH_URL ="https://www.reddit.com/api/v1/authorize.compact"; + public static final String OAUTH_API_BASE_URI = "https://oauth.reddit.com"; + public static final String API_BASE_URI = "https://www.reddit.com"; + public static final String API_UPLOAD_MEDIA_URI = "https://reddit-uploaded-media.s3-accelerate.amazonaws.com"; + public static final String API_UPLOAD_VIDEO_URI = "https://reddit-uploaded-video.s3-accelerate.amazonaws.com"; + + public static final String CLIENT_ID_KEY = "client_id"; + public static final String CLIENT_ID = ""; + public static final String RESPONSE_TYPE_KEY = "response_type"; + public static final String RESPONSE_TYPE = "code"; + public static final String STATE_KEY = "state"; + public static final String STATE = ""; + public static final String REDIRECT_URI_KEY = "redirect_uri"; + public static final String REDIRECT_URI = ""; + public static final String DURATION_KEY = "duration"; + public static final String DURATION = "permanent"; + public static final String SCOPE_KEY = "scope"; + public static final String SCOPE = "identity edit flair history modconfig modflair modlog modposts modwiki mysubreddits privatemessages read report save submit subscribe vote wikiedit wikiread"; + public static final String ACCESS_TOKEN_KEY = "access_token"; + + public static final String AUTHORIZATION_KEY = "Authorization"; + public static final String AUTHORIZATION_BASE = "bearer "; + public static final String USER_AGENT_KEY = "User-Agent"; + public static final String USER_AGENT = ""; + + public static final String GRANT_TYPE_KEY = "grant_type"; + public static final String GRANT_TYPE_REFRESH_TOKEN = "refresh_token"; + public static final String REFRESH_TOKEN_KEY = "refresh_token"; + + public static final String DIR_KEY = "dir"; + public static final String ID_KEY = "id"; + public static final String RANK_KEY = "rank"; + public static final String DIR_UPVOTE = "1"; + public static final String DIR_UNVOTE = "0"; + public static final String DIR_DOWNVOTE = "-1"; + public static final String RANK = "10"; + + public static final String ACTION_KEY = "action"; + public static final String SR_NAME_KEY = "sr_name"; + + public static final String API_TYPE_KEY = "api_type"; + public static final String API_TYPE_JSON = "json"; + public static final String RETURN_RTJSON_KEY = "return_rtjson"; + public static final String TEXT_KEY = "text"; + public static final String URL_KEY = "url"; + public static final String VIDEO_POSTER_URL_KEY = "video_poster_url"; + public static final String THING_ID_KEY = "thing_id"; + + public static final String SR_KEY = "sr"; + public static final String TITLE_KEY = "title"; + public static final String FLAIR_TEXT_KEY = "flair_text"; + public static final String SPOILER_KEY = "spoiler"; + public static final String NSFW_KEY = "nsfw"; + public static final String KIND_KEY = "kind"; + public static final String KIND_SELF = "self"; + public static final String KIND_LINK = "link"; + public static final String KIND_IMAGE = "image"; + public static final String KIND_VIDEO = "video"; + public static final String KIND_VIDEOGIF = "videogif"; + + public static final String FILEPATH_KEY = "filepath"; + public static final String MIMETYPE_KEY = "mimetype"; + + public static final String LINK_KEY = "link"; + public static final String FLAIR_TEMPLATE_ID_KEY = "flair_template_id"; + + public static Map getHttpBasicAuthHeader() { Map params = new HashMap<>(); String credentials = String.format("%s:%s", RedditUtils.CLIENT_ID, ""); String auth = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); @@ -94,7 +94,7 @@ public class RedditUtils { return params; } - static RequestBody getRequestBody(String s) { + public static RequestBody getRequestBody(String s) { return RequestBody.create(MediaType.parse("text/plain"), s); } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Rule.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Rule.java index 89b4d26d..816ab714 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Rule.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Rule.java @@ -1,19 +1,19 @@ package ml.docilealligator.infinityforreddit; -class Rule { +public class Rule { private String shortName; private String descriptionHtml; - Rule(String shortName, String descriptionHtml) { + public Rule(String shortName, String descriptionHtml) { this.shortName = shortName; this.descriptionHtml = descriptionHtml; } - String getShortName() { + public String getShortName() { return shortName; } - String getDescriptionHtml() { + public String getDescriptionHtml() { return descriptionHtml; } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/RulesActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/RulesActivity.java deleted file mode 100644 index 20e3e4d9..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/RulesActivity.java +++ /dev/null @@ -1,279 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.AsyncTask; -import android.os.Build; -import android.os.Bundle; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.ProgressBar; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.google.android.material.appbar.AppBarLayout; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class RulesActivity extends AppCompatActivity { - - static final String EXTRA_SUBREDDIT_NAME = "ESN"; - - @BindView(R.id.appbar_layout_rules_activity) AppBarLayout appBarLayout; - @BindView(R.id.toolbar_rules_activity) Toolbar toolbar; - @BindView(R.id.progress_bar_rules_activity) ProgressBar progressBar; - @BindView(R.id.recycler_view_rules_activity) RecyclerView recyclerView; - @BindView(R.id.error_text_view_rules_activity) TextView errorTextView; - - private String mSubredditName; - - private RulesRecyclerViewAdapter mAdapter; - - @Inject - @Named("no_oauth") - Retrofit mRetrofit; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_rules); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - Resources resources = getResources(); - - if(resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { - Window window = getWindow(); - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - - boolean lightNavBar = false; - if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - lightNavBar = true; - } - boolean finalLightNavBar = lightNavBar; - - View decorView = window.getDecorView(); - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { - @Override - void onStateChanged(AppBarLayout appBarLayout, State state) { - if(state == State.COLLAPSED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } else if(state == State.EXPANDED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } - } - }); - - int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); - if (statusBarResourceId > 0) { - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); - params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); - toolbar.setLayoutParams(params); - } - - if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { - int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); - if (navBarResourceId > 0) { - recyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); - } - } - } - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - mSubredditName = getIntent().getExtras().getString(EXTRA_SUBREDDIT_NAME); - - recyclerView.setLayoutManager(new LinearLayoutManager(this)); - mAdapter = new RulesRecyclerViewAdapter(this); - recyclerView.setAdapter(mAdapter); - - fetchRules(); - } - - private void fetchRules() { - progressBar.setVisibility(View.VISIBLE); - errorTextView.setVisibility(View.GONE); - - RedditAPI api = mRetrofit.create(RedditAPI.class); - Call rulesCall = api.getRules(mSubredditName); - rulesCall.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if(response.isSuccessful()) { - new ParseRulesAsyncTask(response.body(), new ParseRulesAsyncTask.ParseRulesAsyncTaskListener() { - @Override - public void parseSuccessful(ArrayList rules) { - progressBar.setVisibility(View.GONE); - if(rules == null || rules.size() == 0) { - errorTextView.setVisibility(View.VISIBLE); - errorTextView.setText(R.string.no_rule); - errorTextView.setOnClickListener(view -> {}); - } - mAdapter.changeDataset(rules); - } - - @Override - public void parseFailed() { - displayError(); - } - }).execute(); - } else { - displayError(); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - displayError(); - } - }); - } - - private void displayError() { - progressBar.setVisibility(View.GONE); - errorTextView.setVisibility(View.VISIBLE); - errorTextView.setText(R.string.error_loading_rules); - errorTextView.setOnClickListener(view -> fetchRules()); - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if(item.getItemId() == android.R.id.home) { - finish(); - return true; - } - - return false; - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } - - private static class ParseRulesAsyncTask extends AsyncTask, ArrayList> { - private String response; - private ParseRulesAsyncTaskListener parseRulesAsyncTaskListener; - - interface ParseRulesAsyncTaskListener { - void parseSuccessful(ArrayList rules); - void parseFailed(); - } - - ParseRulesAsyncTask(String response, ParseRulesAsyncTaskListener parseRulesAsyncTaskListener) { - this.response = response; - this.parseRulesAsyncTaskListener = parseRulesAsyncTaskListener; - } - - @Override - protected ArrayList doInBackground(Void... voids) { - try { - JSONArray rulesArray = new JSONObject(response).getJSONArray(JSONUtils.RULES_KEY); - ArrayList rules = new ArrayList<>(); - for(int i = 0; i < rulesArray.length(); i++) { - String shortName = rulesArray.getJSONObject(i).getString(JSONUtils.SHORT_NAME_KEY); - String description = null; - if(rulesArray.getJSONObject(i).has(JSONUtils.DESCRIPTION_KEY)) { - description = Utils.addSubredditAndUserLink(rulesArray.getJSONObject(i).getString(JSONUtils.DESCRIPTION_KEY)); - } - rules.add(new Rule(shortName, description)); - } - return rules; - } catch (JSONException e) { - e.printStackTrace(); - } - return null; - } - - @Override - protected void onPostExecute(ArrayList rules) { - if(rules != null) { - parseRulesAsyncTaskListener.parseSuccessful(rules); - } else { - parseRulesAsyncTaskListener.parseFailed(); - } - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/RulesRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/RulesRecyclerViewAdapter.java deleted file mode 100644 index 4ab0f201..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/RulesRecyclerViewAdapter.java +++ /dev/null @@ -1,92 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.text.util.Linkify; -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.ArrayList; - -import butterknife.BindView; -import butterknife.ButterKnife; -import io.noties.markwon.AbstractMarkwonPlugin; -import io.noties.markwon.Markwon; -import io.noties.markwon.MarkwonConfiguration; -import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; -import io.noties.markwon.linkify.LinkifyPlugin; - -class RulesRecyclerViewAdapter extends RecyclerView.Adapter { - private Markwon markwon; - private ArrayList rules; - - RulesRecyclerViewAdapter(Context context) { - markwon = Markwon.builder(context) - .usePlugin(new AbstractMarkwonPlugin() { - @Override - public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { - builder.linkResolver((view, link) -> { - Intent intent = new Intent(context, LinkResolverActivity.class); - Uri uri = Uri.parse(link); - if(uri.getScheme() == null && uri.getHost() == null) { - intent.setData(LinkResolverActivity.getRedditUriByPath(link)); - } else { - intent.setData(uri); - } - context.startActivity(intent); - }); - } - }) - .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS)) - .usePlugin(StrikethroughPlugin.create()) - .build(); - } - - @NonNull - @Override - public RuleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new RuleViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_rule, parent, false)); - } - - @Override - public void onBindViewHolder(@NonNull RuleViewHolder holder, int position) { - holder.shortNameTextView.setText(rules.get(holder.getAdapterPosition()).getShortName()); - if(rules.get(holder.getAdapterPosition()).getDescriptionHtml() == null) { - holder.descriptionMarkwonView.setVisibility(View.GONE); - } else { - markwon.setMarkdown(holder.descriptionMarkwonView, rules.get(holder.getAdapterPosition()).getDescriptionHtml()); - } - } - - @Override - public int getItemCount() { - return rules == null ? 0 : rules.size(); - } - - @Override - public void onViewRecycled(@NonNull RuleViewHolder holder) { - super.onViewRecycled(holder); - holder.descriptionMarkwonView.setVisibility(View.VISIBLE); - } - - void changeDataset(ArrayList rules) { - this.rules = rules; - notifyDataSetChanged(); - } - - class RuleViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.short_name_text_view_item_rule) TextView shortNameTextView; - @BindView(R.id.description_markwon_view_item_rule) TextView descriptionMarkwonView; - - RuleViewHolder(@NonNull View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SaveThing.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SaveThing.java index 743fec29..bae1b1bc 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SaveThing.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SaveThing.java @@ -10,14 +10,14 @@ import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; -class SaveThing { - interface SaveThingListener { +public class SaveThing { + public interface SaveThingListener { void success(); void failed(); } - static void saveThing(Retrofit oauthRetrofit, String accessToken, String fullname, - SaveThingListener saveThingListener) { + public static void saveThing(Retrofit oauthRetrofit, String accessToken, String fullname, + SaveThingListener saveThingListener) { Map params = new HashMap<>(); params.put(RedditUtils.ID_KEY, fullname); oauthRetrofit.create(RedditAPI.class).save(RedditUtils.getOAuthHeader(accessToken), params).enqueue(new Callback() { @@ -37,8 +37,8 @@ class SaveThing { }); } - static void unsaveThing(Retrofit oauthRetrofit, String accessToken, String fullname, - SaveThingListener saveThingListener) { + public static void unsaveThing(Retrofit oauthRetrofit, String accessToken, String fullname, + SaveThingListener saveThingListener) { Map params = new HashMap<>(); params.put(RedditUtils.ID_KEY, fullname); oauthRetrofit.create(RedditAPI.class).unsave(RedditUtils.getOAuthHeader(accessToken), params).enqueue(new Callback() { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java deleted file mode 100644 index a0192e36..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java +++ /dev/null @@ -1,298 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.view.inputmethod.InputMethodManager; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.core.content.ContextCompat; - -import com.ferfalk.simplesearchview.SimpleSearchView; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import javax.inject.Inject; - -import butterknife.BindView; -import butterknife.ButterKnife; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class SearchActivity extends AppCompatActivity { - - static final String EXTRA_QUERY = "EQ"; - static final String EXTRA_SUBREDDIT_NAME = "ESN"; - static final String EXTRA_SUBREDDIT_IS_USER = "ESIU"; - static final String EXTRA_SEARCH_ONLY_SUBREDDITS = "ESOS"; - static final String EXTRA_RETURN_SUBREDDIT_NAME = "ERSN"; - static final String EXTRA_RETURN_SUBREDDIT_ICON_URL = "ERSIURL"; - - private static final String SUBREDDIT_NAME_STATE = "SNS"; - private static final String SUBREDDIT_IS_USER_STATE = "SIUS"; - - private static final int SUBREDDIT_SELECTION_REQUEST_CODE = 0; - private static final int SUBREDDIT_SEARCH_REQUEST_CODE = 1; - - @BindView(R.id.toolbar) Toolbar toolbar; - @BindView(R.id.search_view_search_activity) SimpleSearchView simpleSearchView; - @BindView(R.id.subreddit_name_relative_layout_search_activity) RelativeLayout subredditNameRelativeLayout; - @BindView(R.id.subreddit_name_text_view_search_activity) TextView subredditNameTextView; - - private String query; - private String subredditName; - private boolean subredditIsUser; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_search); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - Window window = getWindow(); - if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - setSupportActionBar(toolbar); - - boolean searchOnlySubreddits = getIntent().getExtras().getBoolean(EXTRA_SEARCH_ONLY_SUBREDDITS); - - simpleSearchView.setOnSearchViewListener(new SimpleSearchView.SearchViewListener() { - @Override - public void onSearchViewShown() { - - } - - @Override - public void onSearchViewClosed() { - finish(); - } - - @Override - public void onSearchViewShownAnimation() { - - } - - @Override - public void onSearchViewClosedAnimation() { - - } - }); - - simpleSearchView.setOnQueryTextListener(new SimpleSearchView.OnQueryTextListener() { - @Override - public boolean onQueryTextSubmit(String query) { - if(searchOnlySubreddits) { - Intent intent = new Intent(SearchActivity.this, SearchSubredditsResultActivity.class); - intent.putExtra(SearchSubredditsResultActivity.EXTRA_QUERY, query); - startActivityForResult(intent, SUBREDDIT_SEARCH_REQUEST_CODE); - } else { - Intent intent = new Intent(SearchActivity.this, SearchResultActivity.class); - intent.putExtra(SearchResultActivity.EXTRA_QUERY, query); - if(subredditName != null) { - if(subredditIsUser) { - intent.putExtra(SearchResultActivity.EXTRA_SUBREDDIT_NAME, "u_" + subredditName); - } else { - intent.putExtra(SearchResultActivity.EXTRA_SUBREDDIT_NAME, subredditName); - } - } - startActivity(intent); - finish(); - } - return true; - } - - @Override - public boolean onQueryTextChange(String newText) { - return false; - } - - @Override - public boolean onQueryTextCleared() { - return false; - } - }); - - if(savedInstanceState != null) { - subredditName = savedInstanceState.getString(SUBREDDIT_NAME_STATE); - subredditIsUser = savedInstanceState.getBoolean(SUBREDDIT_IS_USER_STATE); - - if(subredditName == null) { - subredditNameTextView.setText(R.string.all_subreddits); - } else { - subredditNameTextView.setText(subredditName); - } - } else { - query = getIntent().getStringExtra(EXTRA_QUERY); - } - - if(searchOnlySubreddits) { - subredditNameRelativeLayout.setVisibility(View.GONE); - } else { - subredditNameRelativeLayout.setOnClickListener(view -> { - Intent intent = new Intent(this, SubredditSelectionActivity.class); - intent.putExtra(SubredditSelectionActivity.EXTRA_EXTRA_CLEAR_SELECTION, true); - startActivityForResult(intent, SUBREDDIT_SELECTION_REQUEST_CODE); - }); - } - - Intent intent = getIntent(); - if(intent.hasExtra(EXTRA_SUBREDDIT_NAME)) { - subredditName = intent.getExtras().getString(EXTRA_SUBREDDIT_NAME); - subredditNameTextView.setText(subredditName); - subredditIsUser = intent.getExtras().getBoolean(EXTRA_SUBREDDIT_IS_USER); - } - } - - @Override - protected void onStart() { - super.onStart(); - simpleSearchView.showSearch(false); - simpleSearchView.getSearchEditText().requestFocus(); - - if(query != null) { - simpleSearchView.getSearchEditText().setText(query); - simpleSearchView.getSearchEditText().setSelection(query.length()); - query = null; - } - - InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - if(imm != null) { - imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); - } - } - - @Override - protected void onPause() { - super.onPause(); - InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); - if(imm != null) { - imm.hideSoftInputFromWindow(simpleSearchView.getSearchEditText().getWindowToken(), 0); - } - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - if (simpleSearchView.onActivityResult(requestCode, resultCode, data)) { - return; - } - - if(requestCode == SUBREDDIT_SELECTION_REQUEST_CODE) { - if(resultCode == RESULT_OK) { - subredditName = data.getExtras().getString(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_NAME); - subredditIsUser = data.getExtras().getBoolean(SubredditSelectionActivity.EXTRA_RETURN_SUBREDDIT_IS_USER); - - if(subredditName == null) { - subredditNameTextView.setText(R.string.all_subreddits); - } else { - subredditNameTextView.setText(subredditName); - } - } - } else if(requestCode == SUBREDDIT_SEARCH_REQUEST_CODE) { - if(resultCode == RESULT_OK) { - String name = data.getExtras().getString(SearchSubredditsResultActivity.EXTRA_RETURN_SUBREDDIT_NAME); - String iconUrl = data.getExtras().getString(SearchSubredditsResultActivity.EXTRA_RETURN_SUBREDDIT_ICON_URL); - Intent returnIntent = new Intent(); - returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_NAME, name); - returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_ICON_URL, iconUrl); - setResult(Activity.RESULT_OK, returnIntent); - finish(); - } - } - - super.onActivityResult(requestCode, resultCode, data); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.search_activity, menu); - simpleSearchView.setMenuItem(menu.findItem(R.id.action_search_search_activity)); - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if(item.getItemId() == android.R.id.home) { - finish(); - return true; - } - - return false; - } - - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putString(SUBREDDIT_NAME_STATE, subredditName); - outState.putBoolean(SUBREDDIT_IS_USER_STATE, subredditIsUser); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchPostSortTypeBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SearchPostSortTypeBottomSheetFragment.java deleted file mode 100644 index d0b2bf6b..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchPostSortTypeBottomSheetFragment.java +++ /dev/null @@ -1,82 +0,0 @@ -package ml.docilealligator.infinityforreddit; - - -import android.app.Activity; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.fragment.app.Fragment; - -import com.deishelon.roundedbottomsheet.RoundedBottomSheetDialogFragment; - -import butterknife.BindView; -import butterknife.ButterKnife; - - -/** - * A simple {@link Fragment} subclass. - */ -public class SearchPostSortTypeBottomSheetFragment extends RoundedBottomSheetDialogFragment { - - interface SearchSortTypeSelectionCallback { - void searchSortTypeSelected(String sortType); - } - - @BindView(R.id.relevance_type_text_view_search_sort_type_bottom_sheet_fragment) TextView relevanceTypeTextView; - @BindView(R.id.hot_type_text_view_search_sort_type_bottom_sheet_fragment) TextView hotTypeTextView; - @BindView(R.id.top_type_text_view_search_sort_type_bottom_sheet_fragment) TextView topTypeTextView; - @BindView(R.id.new_type_text_view_search_sort_type_bottom_sheet_fragment) TextView newTypeTextView; - @BindView(R.id.comments_type_text_view_search_sort_type_bottom_sheet_fragment) TextView commentsTypeTextView; - - public SearchPostSortTypeBottomSheetFragment() { - // Required empty public constructor - } - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_search_post_sort_type_bottom_sheet, container, false); - ButterKnife.bind(this, rootView); - - Activity activity = getActivity(); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O - && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - - relevanceTypeTextView.setOnClickListener(view -> { - ((SearchSortTypeSelectionCallback) activity).searchSortTypeSelected(PostDataSource.SORT_TYPE_RELEVANCE); - dismiss(); - }); - - hotTypeTextView.setOnClickListener(view -> { - ((SearchSortTypeSelectionCallback) activity).searchSortTypeSelected(PostDataSource.SORT_TYPE_HOT); - dismiss(); - }); - - topTypeTextView.setOnClickListener(view -> { - ((SearchSortTypeSelectionCallback) activity).searchSortTypeSelected(PostDataSource.SORT_TYPE_TOP); - dismiss(); - }); - - newTypeTextView.setOnClickListener(view -> { - ((SearchSortTypeSelectionCallback) activity).searchSortTypeSelected(PostDataSource.SORT_TYPE_NEW); - dismiss(); - }); - - commentsTypeTextView.setOnClickListener(view -> { - ((SearchSortTypeSelectionCallback) activity).searchSortTypeSelected(PostDataSource.SORT_TYPE_COMMENTS); - dismiss(); - }); - - return rootView; - } - -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchResultActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SearchResultActivity.java deleted file mode 100644 index 5967066b..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchResultActivity.java +++ /dev/null @@ -1,394 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentPagerAdapter; -import androidx.viewpager.widget.ViewPager; - -import com.google.android.material.appbar.AppBarLayout; -import com.google.android.material.tabs.TabLayout; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import javax.inject.Inject; - -import butterknife.BindView; -import butterknife.ButterKnife; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class SearchResultActivity extends AppCompatActivity implements SearchPostSortTypeBottomSheetFragment.SearchSortTypeSelectionCallback, - SearchUserAndSubredditSortTypeBottomSheetFragment.SearchUserAndSubredditSortTypeSelectionCallback { - static final String EXTRA_QUERY = "QK"; - static final String EXTRA_SUBREDDIT_NAME = "ESN"; - - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - private static final String ACCOUNT_NAME_STATE = "ANS"; - - private boolean mNullAccessToken = false; - private String mAccessToken; - private String mAccountName; - private String mQuery; - private String mSubredditName; - - @BindView(R.id.appbar_layout_search_result_activity) AppBarLayout appBarLayout; - @BindView(R.id.toolbar_search_result_activity) Toolbar toolbar; - @BindView(R.id.tab_layout_search_result_activity) TabLayout tabLayout; - @BindView(R.id.view_pager_search_result_activity) ViewPager viewPager; - - private SectionsPagerAdapter sectionsPagerAdapter; - - private SearchPostSortTypeBottomSheetFragment searchPostSortTypeBottomSheetFragment; - private SearchUserAndSubredditSortTypeBottomSheetFragment searchUserAndSubredditSortTypeBottomSheetFragment; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_search_result); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - Resources resources = getResources(); - - if(resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { - Window window = getWindow(); - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - - boolean lightNavBar = false; - if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - lightNavBar = true; - } - boolean finalLightNavBar = lightNavBar; - - View decorView = window.getDecorView(); - appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { - @Override - void onStateChanged(AppBarLayout appBarLayout, State state) { - if(state == State.COLLAPSED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } else if(state == State.EXPANDED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } - } - }); - - int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); - if (statusBarResourceId > 0) { - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); - params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); - toolbar.setLayoutParams(params); - } - } - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - if(savedInstanceState == null) { - getCurrentAccountAndInitializeViewPager(); - } else { - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); - if(!mNullAccessToken && mAccessToken == null) { - getCurrentAccountAndInitializeViewPager(); - } else { - initializeViewPager(); - } - } - - searchPostSortTypeBottomSheetFragment = new SearchPostSortTypeBottomSheetFragment(); - Bundle bundle = new Bundle(); - searchPostSortTypeBottomSheetFragment.setArguments(bundle); - - searchUserAndSubredditSortTypeBottomSheetFragment = new SearchUserAndSubredditSortTypeBottomSheetFragment(); - - // Get the intent, verify the action and get the query - Intent intent = getIntent(); - String query = intent.getStringExtra(EXTRA_QUERY); - - mSubredditName = intent.getStringExtra(EXTRA_SUBREDDIT_NAME); - - if(query != null) { - mQuery = query; - setTitle(query); - } - } - - private void getCurrentAccountAndInitializeViewPager() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - } - initializeViewPager(); - }).execute(); - } - - private void initializeViewPager() { - sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); - viewPager.setAdapter(sectionsPagerAdapter); - viewPager.setOffscreenPageLimit(2); - tabLayout.setupWithViewPager(viewPager); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.search_result_activity, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - onBackPressed(); - return true; - case R.id.action_sort_search_result_activity: - switch (viewPager.getCurrentItem()) { - case 0: { - searchPostSortTypeBottomSheetFragment.show(getSupportFragmentManager(), searchPostSortTypeBottomSheetFragment.getTag()); - break; - } - case 1: - case 2: - Bundle bundle = new Bundle(); - bundle.putInt(SearchUserAndSubredditSortTypeBottomSheetFragment.EXTRA_FRAGMENT_POSITION, viewPager.getCurrentItem()); - searchUserAndSubredditSortTypeBottomSheetFragment.setArguments(bundle); - searchUserAndSubredditSortTypeBottomSheetFragment.show(getSupportFragmentManager(), searchUserAndSubredditSortTypeBottomSheetFragment.getTag()); - break; - } - return true; - case R.id.action_search_search_result_activity: - Intent intent = new Intent(this, SearchActivity.class); - intent.putExtra(SearchActivity.EXTRA_SEARCH_ONLY_SUBREDDITS, false); - intent.putExtra(SearchActivity.EXTRA_QUERY, mQuery); - finish(); - startActivity(intent); - return true; - case R.id.action_refresh_search_result_activity: - sectionsPagerAdapter.refresh(); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - outState.putString(ACCOUNT_NAME_STATE, mAccountName); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - @Override - public void searchSortTypeSelected(String sortType) { - sectionsPagerAdapter.changeSortType(sortType, 0); - } - - @Override - public void searchUserAndSubredditSortTypeSelected(String sortType, int fragmentPosition) { - sectionsPagerAdapter.changeSortType(sortType, fragmentPosition); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } - - @Subscribe - public void onChangeNSFWEvent(ChangeNSFWEvent changeNSFWEvent) { - sectionsPagerAdapter.changeNSFW(changeNSFWEvent.nsfw); - } - - private class SectionsPagerAdapter extends FragmentPagerAdapter { - - private PostFragment postFragment; - private SubredditListingFragment subredditListingFragment; - private UserListingFragment userListingFragment; - - public SectionsPagerAdapter(FragmentManager fm) { - super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); - } - - @NonNull - @Override - public Fragment getItem(int position) { - switch (position) { - case 0: { - PostFragment mFragment = new PostFragment(); - Bundle bundle = new Bundle(); - bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_SEARCH); - bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_RELEVANCE); - bundle.putString(PostFragment.EXTRA_NAME, mSubredditName); - bundle.putString(PostFragment.EXTRA_QUERY, mQuery); - bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); - bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - mFragment.setArguments(bundle); - return mFragment; - } - case 1: { - SubredditListingFragment mFragment = new SubredditListingFragment(); - Bundle bundle = new Bundle(); - bundle.putString(SubredditListingFragment.EXTRA_QUERY, mQuery); - bundle.putBoolean(SubredditListingFragment.EXTRA_IS_POSTING, false); - bundle.putString(SubredditListingFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - bundle.putString(SubredditListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); - mFragment.setArguments(bundle); - return mFragment; - } - default: { - UserListingFragment mFragment = new UserListingFragment(); - Bundle bundle = new Bundle(); - bundle.putString(UserListingFragment.EXTRA_QUERY, mQuery); - bundle.putString(UserListingFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - bundle.putString(UserListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); - mFragment.setArguments(bundle); - return mFragment; - } - } - } - - @Override - public int getCount() { - return 3; - } - - @Override - public CharSequence getPageTitle(int position) { - switch (position) { - case 0: - return "Posts"; - case 1: - return "Subreddits"; - case 2: - return "Users"; - } - return null; - } - - @NonNull - @Override - public Object instantiateItem(@NonNull ViewGroup container, int position) { - Fragment fragment = (Fragment) super.instantiateItem(container, position); - switch (position) { - case 0: - postFragment = (PostFragment) fragment; - break; - case 1: - subredditListingFragment = (SubredditListingFragment) fragment; - break; - case 2: - userListingFragment = (UserListingFragment) fragment; - break; - } - return fragment; - } - - void changeSortType(String sortType, int fragmentPosition) { - switch (fragmentPosition) { - case 0: - postFragment.changeSortType(sortType); - break; - case 1: - subredditListingFragment.changeSortType(sortType); - break; - case 2: - userListingFragment.changeSortType(sortType); - } - } - - public void refresh() { - switch (viewPager.getCurrentItem()) { - case 0: - ((FragmentCommunicator) postFragment).refresh(); - break; - case 1: - ((FragmentCommunicator) subredditListingFragment).refresh(); - break; - case 2: - ((FragmentCommunicator) userListingFragment).refresh(); - break; - } - } - - public void changeNSFW(boolean nsfw) { - if(postFragment != null) { - postFragment.changeNSFW(nsfw); - } - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchSubredditsResultActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SearchSubredditsResultActivity.java deleted file mode 100644 index f9ed0272..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchSubredditsResultActivity.java +++ /dev/null @@ -1,218 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.app.Activity; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.os.Bundle; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.fragment.app.Fragment; - -import com.google.android.material.appbar.AppBarLayout; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import javax.inject.Inject; - -import butterknife.BindView; -import butterknife.ButterKnife; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class SearchSubredditsResultActivity extends AppCompatActivity { - - static final String EXTRA_QUERY = "EQ"; - static final String EXTRA_RETURN_SUBREDDIT_NAME = "ERSN"; - static final String EXTRA_RETURN_SUBREDDIT_ICON_URL = "ERSIURL"; - - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - private static final String ACCOUNT_NAME_STATE = "ANS"; - private static final String FRAGMENT_OUT_STATE = "FOS"; - - @BindView(R.id.appbar_layout_search_subreddits_result_activity) AppBarLayout appBarLayout; - @BindView(R.id.toolbar_search_subreddits_result_activity) Toolbar toolbar; - - private boolean mNullAccessToken = false; - private String mAccessToken; - private String mAccountName; - - Fragment mFragment; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_search_subreddits_result); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - Resources resources = getResources(); - - if(resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { - Window window = getWindow(); - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - - boolean lightNavBar = false; - if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - lightNavBar = true; - } - boolean finalLightNavBar = lightNavBar; - - View decorView = window.getDecorView(); - appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { - @Override - void onStateChanged(AppBarLayout appBarLayout, State state) { - if(state == State.COLLAPSED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } else if(state == State.EXPANDED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } - } - }); - - int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); - if (statusBarResourceId > 0) { - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); - params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); - toolbar.setLayoutParams(params); - } - } - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - String query = getIntent().getExtras().getString(EXTRA_QUERY); - - if(savedInstanceState == null) { - getCurrentAccountAndInitializeFragment(query); - } else { - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); - if(!mNullAccessToken && mAccessToken == null) { - getCurrentAccountAndInitializeFragment(query); - } else { - mFragment = getSupportFragmentManager().getFragment(savedInstanceState, FRAGMENT_OUT_STATE); - getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_search_subreddits_result_activity, mFragment).commit(); - } - } - } - - private void getCurrentAccountAndInitializeFragment(String query) { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - } - - mFragment = new SubredditListingFragment(); - Bundle bundle = new Bundle(); - bundle.putString(SubredditListingFragment.EXTRA_QUERY, query); - bundle.putBoolean(SubredditListingFragment.EXTRA_IS_POSTING, true); - bundle.putString(SubredditListingFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - bundle.putString(SubredditListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); - mFragment.setArguments(bundle); - getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_search_subreddits_result_activity, mFragment).commit(); - }).execute(); - } - - void getSelectedSubreddit(String name, String iconUrl) { - Intent returnIntent = new Intent(); - returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_NAME, name); - returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_ICON_URL, iconUrl); - setResult(Activity.RESULT_OK, returnIntent); - finish(); - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if(item.getItemId() == android.R.id.home) { - finish(); - return true; - } - return false; - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - if (mFragment != null) { - getSupportFragmentManager().putFragment(outState, FRAGMENT_OUT_STATE, mFragment); - } - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - outState.putString(ACCOUNT_NAME_STATE, mAccountName); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchUserAndSubredditSortTypeBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SearchUserAndSubredditSortTypeBottomSheetFragment.java deleted file mode 100644 index 5579d220..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchUserAndSubredditSortTypeBottomSheetFragment.java +++ /dev/null @@ -1,68 +0,0 @@ -package ml.docilealligator.infinityforreddit; - - -import android.app.Activity; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.fragment.app.Fragment; - -import com.deishelon.roundedbottomsheet.RoundedBottomSheetDialogFragment; - -import butterknife.BindView; -import butterknife.ButterKnife; - - -/** - * A simple {@link Fragment} subclass. - */ -public class SearchUserAndSubredditSortTypeBottomSheetFragment extends RoundedBottomSheetDialogFragment { - - interface SearchUserAndSubredditSortTypeSelectionCallback { - void searchUserAndSubredditSortTypeSelected(String sortType, int fragmentPosition); - } - - static final String EXTRA_FRAGMENT_POSITION = "EFP"; - - @BindView(R.id.relevance_type_text_view_search_user_and_subreddit_sort_type_bottom_sheet_fragment) TextView relevanceTypeTextView; - @BindView(R.id.activity_type_text_view_search_user_and_subreddit_sort_type_bottom_sheet_fragment) TextView activityTypeTextView; - - public SearchUserAndSubredditSortTypeBottomSheetFragment() { - // Required empty public constructor - } - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_search_user_and_subreddit_sort_type_bottom_sheet, container, false); - ButterKnife.bind(this, rootView); - - Activity activity = getActivity(); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O - && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - - int position = getArguments().getInt(EXTRA_FRAGMENT_POSITION); - - relevanceTypeTextView.setOnClickListener(view -> { - ((SearchUserAndSubredditSortTypeSelectionCallback) activity).searchUserAndSubredditSortTypeSelected(PostDataSource.SORT_TYPE_RELEVANCE, position); - dismiss(); - }); - - activityTypeTextView.setOnClickListener(view -> { - ((SearchUserAndSubredditSortTypeSelectionCallback) activity).searchUserAndSubredditSortTypeSelected(PostDataSource.SORT_TYPE_HOT, position); - dismiss(); - }); - - return rootView; - } - -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SendComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SendComment.java index 6be33004..b27a70a2 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SendComment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SendComment.java @@ -12,16 +12,16 @@ import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; -class SendComment { +public class SendComment { - interface SendCommentListener { + public interface SendCommentListener { void sendCommentSuccess(CommentData commentData); void sendCommentFailed(String errorMessage); } - static void sendComment(String commentMarkdown, String thingFullname, int parentDepth, - Locale locale, Retrofit oauthRetrofit, String accessToken, - SendCommentListener sendCommentListener) { + public static void sendComment(String commentMarkdown, String thingFullname, int parentDepth, + Locale locale, Retrofit oauthRetrofit, String accessToken, + SendCommentListener sendCommentListener) { RedditAPI api = oauthRetrofit.create(RedditAPI.class); Map headers = RedditUtils.getOAuthHeader(accessToken); Map params = new HashMap<>(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/AboutPreferenceFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/AboutPreferenceFragment.java index 03b904d3..d32a9b06 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/AboutPreferenceFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/AboutPreferenceFragment.java @@ -10,7 +10,7 @@ import android.widget.Toast; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; -import ml.docilealligator.infinityforreddit.LinkResolverActivity; +import ml.docilealligator.infinityforreddit.Activity.LinkResolverActivity; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/AcknowledgementRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/AcknowledgementRecyclerViewAdapter.java index 6c3975ab..0c46c7f6 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/AcknowledgementRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/AcknowledgementRecyclerViewAdapter.java @@ -14,7 +14,7 @@ import java.util.ArrayList; import butterknife.BindView; import butterknife.ButterKnife; -import ml.docilealligator.infinityforreddit.LinkResolverActivity; +import ml.docilealligator.infinityforreddit.Activity.LinkResolverActivity; import ml.docilealligator.infinityforreddit.R; class AcknowledgementRecyclerViewAdapter extends RecyclerView.Adapter { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/CreditsPreferenceFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/CreditsPreferenceFragment.java index bbd98d13..a95d8eb7 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/CreditsPreferenceFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/CreditsPreferenceFragment.java @@ -9,7 +9,7 @@ import android.os.Bundle; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; -import ml.docilealligator.infinityforreddit.LinkResolverActivity; +import ml.docilealligator.infinityforreddit.Activity.LinkResolverActivity; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/FontSizePreferenceFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/FontSizePreferenceFragment.java index c1f89842..69a2a92f 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/FontSizePreferenceFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/FontSizePreferenceFragment.java @@ -8,7 +8,7 @@ import androidx.preference.PreferenceFragmentCompat; import org.greenrobot.eventbus.EventBus; -import ml.docilealligator.infinityforreddit.ChangeFontSizeEvent; +import ml.docilealligator.infinityforreddit.Event.ChangeFontSizeEvent; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/MainPreferenceFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/MainPreferenceFragment.java index 7f72da36..a20ecf55 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/MainPreferenceFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Settings/MainPreferenceFragment.java @@ -15,9 +15,9 @@ import org.greenrobot.eventbus.EventBus; import javax.inject.Inject; -import ml.docilealligator.infinityforreddit.ChangeNSFWBlurEvent; -import ml.docilealligator.infinityforreddit.ChangeNSFWEvent; -import ml.docilealligator.infinityforreddit.ChangeSpoilerBlurEvent; +import ml.docilealligator.infinityforreddit.Event.ChangeNSFWBlurEvent; +import ml.docilealligator.infinityforreddit.Event.ChangeNSFWEvent; +import ml.docilealligator.infinityforreddit.Event.ChangeSpoilerBlurEvent; import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.SharedPreferencesUtils; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SettingsActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SettingsActivity.java deleted file mode 100644 index cf84d82f..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SettingsActivity.java +++ /dev/null @@ -1,148 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.core.content.ContextCompat; -import androidx.fragment.app.Fragment; -import androidx.preference.Preference; -import androidx.preference.PreferenceFragmentCompat; - -import javax.inject.Inject; - -import ml.docilealligator.infinityforreddit.Settings.AboutPreferenceFragment; -import ml.docilealligator.infinityforreddit.Settings.MainPreferenceFragment; -import butterknife.BindView; -import butterknife.ButterKnife; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class SettingsActivity extends AppCompatActivity implements - PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { - - private static final String TITLE_STATE = "TS"; - - @BindView(R.id.toolbar_settings_activity) Toolbar toolbar; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.settings_activity); - - ButterKnife.bind(this); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - Window window = getWindow(); - if((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - window.setNavigationBarColor(ContextCompat.getColor(this, R.color.navBarColor)); - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - setSupportActionBar(toolbar); - - if (savedInstanceState == null) { - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.frame_layout_settings_activity, new MainPreferenceFragment()) - .commit(); - } else { - setTitle(savedInstanceState.getCharSequence(TITLE_STATE)); - } - getSupportFragmentManager().addOnBackStackChangedListener(() -> { - if (getSupportFragmentManager().getBackStackEntryCount() == 0) { - setTitle(R.string.settings_activity_label); - } else if (getSupportFragmentManager().findFragmentById(R.id.frame_layout_settings_activity) instanceof AboutPreferenceFragment) { - setTitle(R.string.settings_about_master_title); - } - }); - - - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if(item.getItemId() == android.R.id.home) { - onBackPressed(); - return true; - } - return false; - } - - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putCharSequence(TITLE_STATE, getTitle()); - } - - @Override - public boolean onSupportNavigateUp() { - if (getSupportFragmentManager().popBackStackImmediate()) { - return true; - } - return super.onSupportNavigateUp(); - } - - @Override - public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) { - // Instantiate the new Fragment - final Bundle args = pref.getExtras(); - final Fragment fragment = getSupportFragmentManager().getFragmentFactory().instantiate( - getClassLoader(), - pref.getFragment()); - fragment.setArguments(args); - fragment.setTargetFragment(caller, 0); - - getSupportFragmentManager().beginTransaction() - .replace(R.id.frame_layout_settings_activity, fragment) - .addToBackStack(null) - .commit(); - setTitle(pref.getTitle()); - return true; - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ShareDataResolverActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ShareDataResolverActivity.java deleted file mode 100644 index 92d2b290..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ShareDataResolverActivity.java +++ /dev/null @@ -1,77 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.util.Patterns; -import android.widget.Toast; - -import androidx.appcompat.app.AppCompatActivity; - -public class ShareDataResolverActivity extends AppCompatActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - Intent receivedIntent = getIntent(); - String action = receivedIntent.getAction(); - String type = receivedIntent.getType(); - - if(Intent.ACTION_SEND.equals(action) && type != null) { - if("text/plain".equals(type)) { - String text = receivedIntent.getStringExtra(Intent.EXTRA_TEXT); - if(text != null) { - if(Patterns.WEB_URL.matcher(text).matches()) { - //It's a link - Intent intent = new Intent(this, PostLinkActivity.class); - intent.putExtra(PostLinkActivity.EXTRA_LINK, text); - startActivity(intent); - } else { - Intent intent = new Intent(this, PostTextActivity.class); - intent.putExtra(PostTextActivity.EXTRA_CONTENT, text); - startActivity(intent); - } - } else { - Toast.makeText(this, R.string.no_data_received, Toast.LENGTH_SHORT).show(); - } - } else if(type.equals("image/gif")) { - Uri videoUri = receivedIntent.getParcelableExtra(Intent.EXTRA_STREAM); - if(videoUri != null) { - Intent intent = new Intent(this, PostVideoActivity.class); - intent.setData(videoUri); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - startActivity(intent); - } else { - Toast.makeText(this, R.string.no_video_path_received, Toast.LENGTH_SHORT).show(); - } - } else if(type.startsWith("image/")) { - Uri imageUri = receivedIntent.getParcelableExtra(Intent.EXTRA_STREAM); - if(imageUri != null) { - Intent intent = new Intent(this, PostImageActivity.class); - intent.setData(imageUri); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - startActivity(intent); - } else { - Toast.makeText(this, R.string.no_image_path_received, Toast.LENGTH_SHORT).show(); - } - } else if(type.startsWith("video/")) { - Uri videoUri = receivedIntent.getParcelableExtra(Intent.EXTRA_STREAM); - if(videoUri != null) { - Intent intent = new Intent(this, PostVideoActivity.class); - intent.setData(videoUri); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - startActivity(intent); - } else { - Toast.makeText(this, R.string.no_video_path_received, Toast.LENGTH_SHORT).show(); - } - } else { - Toast.makeText(this, R.string.cannot_handle_intent, Toast.LENGTH_SHORT).show(); - } - } else { - Toast.makeText(this, R.string.cannot_handle_intent, Toast.LENGTH_SHORT).show(); - } - - finish(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SortTypeBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SortTypeBottomSheetFragment.java deleted file mode 100644 index b4825274..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SortTypeBottomSheetFragment.java +++ /dev/null @@ -1,101 +0,0 @@ -package ml.docilealligator.infinityforreddit; - - -import android.app.Activity; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; - -import com.deishelon.roundedbottomsheet.RoundedBottomSheetDialogFragment; - -import butterknife.BindView; -import butterknife.ButterKnife; - - -/** - * A simple {@link Fragment} subclass. - */ -public class SortTypeBottomSheetFragment extends RoundedBottomSheetDialogFragment { - - interface SortTypeSelectionCallback { - void sortTypeSelected(String sortType); - } - - static final String EXTRA_NO_BEST_TYPE = "ENBT"; - - @BindView(R.id.best_type_text_view_sort_type_bottom_sheet_fragment) TextView bestTypeTextView; - @BindView(R.id.hot_type_text_view_sort_type_bottom_sheet_fragment) TextView hotTypeTextView; - @BindView(R.id.new_type_text_view_sort_type_bottom_sheet_fragment) TextView newTypeTextView; - @BindView(R.id.random_type_text_view_sort_type_bottom_sheet_fragment) TextView randomTypeTextView; - @BindView(R.id.rising_type_text_view_sort_type_bottom_sheet_fragment) TextView risingTypeTextView; - @BindView(R.id.top_type_text_view_sort_type_bottom_sheet_fragment) TextView topTypeTextView; - @BindView(R.id.controversial_type_text_view_sort_type_bottom_sheet_fragment) TextView controversialTypeTextView; - - public SortTypeBottomSheetFragment() { - // Required empty public constructor - } - - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_sort_type_bottom_sheet, container, false); - ButterKnife.bind(this, rootView); - - Activity activity = getActivity(); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O - && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - - if(getArguments().getBoolean(EXTRA_NO_BEST_TYPE)) { - bestTypeTextView.setVisibility(View.GONE); - } else { - bestTypeTextView.setOnClickListener(view -> { - ((SortTypeSelectionCallback) activity).sortTypeSelected(PostDataSource.SORT_TYPE_BEST); - dismiss(); - }); - } - - hotTypeTextView.setOnClickListener(view -> { - ((SortTypeSelectionCallback) activity).sortTypeSelected(PostDataSource.SORT_TYPE_HOT); - dismiss(); - }); - - newTypeTextView.setOnClickListener(view -> { - ((SortTypeSelectionCallback) activity).sortTypeSelected(PostDataSource.SORT_TYPE_NEW); - dismiss(); - }); - - randomTypeTextView.setOnClickListener(view -> { - ((SortTypeSelectionCallback) activity).sortTypeSelected(PostDataSource.SORT_TYPE_RANDOM); - dismiss(); - }); - - risingTypeTextView.setOnClickListener(view -> { - ((SortTypeSelectionCallback) activity).sortTypeSelected(PostDataSource.SORT_TYPE_RISING); - dismiss(); - }); - - topTypeTextView.setOnClickListener(view -> { - ((SortTypeSelectionCallback) activity).sortTypeSelected(PostDataSource.SORT_TYPE_TOP); - dismiss(); - }); - - controversialTypeTextView.setOnClickListener(view -> { - ((SortTypeSelectionCallback) activity).sortTypeSelected(PostDataSource.SORT_TYPE_CONTROVERSIAL); - dismiss(); - }); - - return rootView; - } - -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitImagePostEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitImagePostEvent.java deleted file mode 100644 index 3432628c..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitImagePostEvent.java +++ /dev/null @@ -1,11 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -public class SubmitImagePostEvent { - public boolean postSuccess; - public String errorMessage; - - public SubmitImagePostEvent(boolean postSuccess, String errorMessage) { - this.postSuccess = postSuccess; - this.errorMessage = errorMessage; - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitPostService.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitPostService.java index f3e42109..ebbf2829 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitPostService.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitPostService.java @@ -30,21 +30,24 @@ import java.io.IOException; import javax.inject.Inject; import javax.inject.Named; +import ml.docilealligator.infinityforreddit.Event.SubmitImagePostEvent; +import ml.docilealligator.infinityforreddit.Event.SubmitTextOrLinkPostEvent; +import ml.docilealligator.infinityforreddit.Event.SubmitVideoPostEvent; import retrofit2.Retrofit; public class SubmitPostService extends Service { - static final String EXTRA_ACCESS_TOKEN = "EAT"; - static final String EXTRA_SUBREDDIT_NAME = "ESN"; - static final String EXTRA_TITLE = "ET"; - static final String EXTRA_CONTENT = "EC"; - static final String EXTRA_KIND = "EK"; - static final String EXTRA_FLAIR = "EF"; - static final String EXTRA_IS_SPOILER = "EIS"; - static final String EXTRA_IS_NSFW = "EIN"; - static final String EXTRA_POST_TYPE = "EPT"; - static final int EXTRA_POST_TEXT_OR_LINK = 0; - static final int EXTRA_POST_TYPE_IMAGE = 1; - static final int EXTRA_POST_TYPE_VIDEO = 2; + public static final String EXTRA_ACCESS_TOKEN = "EAT"; + public static final String EXTRA_SUBREDDIT_NAME = "ESN"; + public static final String EXTRA_TITLE = "ET"; + public static final String EXTRA_CONTENT = "EC"; + public static final String EXTRA_KIND = "EK"; + public static final String EXTRA_FLAIR = "EF"; + public static final String EXTRA_IS_SPOILER = "EIS"; + public static final String EXTRA_IS_NSFW = "EIN"; + public static final String EXTRA_POST_TYPE = "EPT"; + public static final int EXTRA_POST_TEXT_OR_LINK = 0; + public static final int EXTRA_POST_TYPE_IMAGE = 1; + public static final int EXTRA_POST_TYPE_VIDEO = 2; private String mAccessToken; private String subredditName; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitTextOrLinkPostEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitTextOrLinkPostEvent.java deleted file mode 100644 index 073298f5..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitTextOrLinkPostEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -public class SubmitTextOrLinkPostEvent { - public boolean postSuccess; - public Post post; - public String errorMessage; - - public SubmitTextOrLinkPostEvent(boolean postSuccess, Post post, String errorMessage) { - this.postSuccess = postSuccess; - this.post = post; - this.errorMessage = errorMessage; - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitVideoPostEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitVideoPostEvent.java deleted file mode 100644 index 6699135f..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubmitVideoPostEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -public class SubmitVideoPostEvent { - public boolean postSuccess; - public boolean errorProcessingVideo; - public String errorMessage; - - public SubmitVideoPostEvent(boolean postSuccess, boolean errorProcessingVideo, String errorMessage) { - this.postSuccess = postSuccess; - this.errorProcessingVideo = errorProcessingVideo; - this.errorMessage = errorMessage; - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingFragment.java deleted file mode 100644 index 03660f57..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingFragment.java +++ /dev/null @@ -1,180 +0,0 @@ -package ml.docilealligator.infinityforreddit; - - -import android.app.Activity; -import android.content.Intent; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProvider; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.bumptech.glide.Glide; -import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import retrofit2.Retrofit; - - -/** - * A simple {@link Fragment} subclass. - */ -public class SubredditListingFragment extends Fragment implements FragmentCommunicator { - - static final String EXTRA_QUERY = "EQ"; - static final String EXTRA_IS_POSTING = "EIP"; - static final String EXTRA_ACCESS_TOKEN = "EAT"; - static final String EXTRA_ACCOUNT_NAME = "EAN"; - - @BindView(R.id.coordinator_layout_subreddit_listing_fragment) CoordinatorLayout mCoordinatorLayout; - @BindView(R.id.recycler_view_subreddit_listing_fragment) RecyclerView mSubredditListingRecyclerView; - @BindView(R.id.progress_bar_subreddit_listing_fragment) CircleProgressBar mProgressBar; - @BindView(R.id.fetch_subreddit_listing_info_linear_layout_subreddit_listing_fragment) LinearLayout mFetchSubredditListingInfoLinearLayout; - @BindView(R.id.fetch_subreddit_listing_info_image_view_subreddit_listing_fragment) ImageView mFetchSubredditListingInfoImageView; - @BindView(R.id.fetch_subreddit_listing_info_text_view_subreddit_listing_fragment) TextView mFetchSubredditListingInfoTextView; - - private LinearLayoutManager mLinearLayoutManager; - - private SubredditListingRecyclerViewAdapter mAdapter; - - SubredditListingViewModel mSubredditListingViewModel; - - @Inject @Named("no_oauth") - Retrofit mRetrofit; - - @Inject @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase redditDataRoomDatabase; - - public SubredditListingFragment() { - // Required empty public constructor - } - - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - // Inflate the layout for this fragment - View rootView = inflater.inflate(R.layout.fragment_subreddit_listing, container, false); - - Activity activity = getActivity(); - - ((Infinity) activity.getApplication()).getAppComponent().inject(this); - - ButterKnife.bind(this, rootView); - - Resources resources = getResources(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { - int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); - if (navBarResourceId > 0) { - mSubredditListingRecyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); - } - } - } - - mLinearLayoutManager = new LinearLayoutManager(getActivity()); - mSubredditListingRecyclerView.setLayoutManager(mLinearLayoutManager); - - String query = getArguments().getString(EXTRA_QUERY); - boolean isPosting = getArguments().getBoolean(EXTRA_IS_POSTING); - String accessToken = getArguments().getString(EXTRA_ACCESS_TOKEN); - String accountName = getArguments().getString(EXTRA_ACCOUNT_NAME); - - mAdapter = new SubredditListingRecyclerViewAdapter(activity, mOauthRetrofit, mRetrofit, - accessToken, accountName, redditDataRoomDatabase, - new SubredditListingRecyclerViewAdapter.Callback() { - @Override - public void retryLoadingMore() { - mSubredditListingViewModel.retryLoadingMore(); - } - - @Override - public void subredditSelected(String subredditName, String iconUrl) { - if(isPosting) { - ((SearchSubredditsResultActivity) activity).getSelectedSubreddit(subredditName, iconUrl); - } else { - Intent intent = new Intent(activity, ViewSubredditDetailActivity.class); - intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, subredditName); - activity.startActivity(intent); - } - } - }); - - mSubredditListingRecyclerView.setAdapter(mAdapter); - - SubredditListingViewModel.Factory factory = new SubredditListingViewModel.Factory(mRetrofit, query, - PostDataSource.SORT_TYPE_RELEVANCE); - mSubredditListingViewModel = new ViewModelProvider(this, factory).get(SubredditListingViewModel.class); - mSubredditListingViewModel.getSubreddits().observe(this, subredditData -> mAdapter.submitList(subredditData)); - - mSubredditListingViewModel.hasSubredditLiveData().observe(this, hasSubreddit -> { - mProgressBar.setVisibility(View.GONE); - if(hasSubreddit) { - mFetchSubredditListingInfoLinearLayout.setVisibility(View.GONE); - } else { - mFetchSubredditListingInfoLinearLayout.setOnClickListener(view -> { - //Do nothing - }); - showErrorView(R.string.no_subreddits); - } - }); - - mSubredditListingViewModel.getInitialLoadingState().observe(this, networkState -> { - if(networkState.getStatus().equals(NetworkState.Status.SUCCESS)) { - mProgressBar.setVisibility(View.GONE); - } else if(networkState.getStatus().equals(NetworkState.Status.FAILED)) { - mProgressBar.setVisibility(View.GONE); - mFetchSubredditListingInfoLinearLayout.setOnClickListener(view -> refresh()); - showErrorView(R.string.search_subreddits_error); - } else { - mProgressBar.setVisibility(View.VISIBLE); - } - }); - - mSubredditListingViewModel.getPaginationNetworkState().observe(this, networkState -> { - mAdapter.setNetworkState(networkState); - }); - - return rootView; - } - - private void showErrorView(int stringResId) { - if(getActivity() != null && isAdded()) { - mProgressBar.setVisibility(View.GONE); - mFetchSubredditListingInfoLinearLayout.setVisibility(View.VISIBLE); - mFetchSubredditListingInfoTextView.setText(stringResId); - Glide.with(this).load(R.drawable.error_image).into(mFetchSubredditListingInfoImageView); - } - } - - void changeSortType(String sortType) { - mSubredditListingViewModel.changeSortType(sortType); - } - - @Override - public void refresh() { - mFetchSubredditListingInfoLinearLayout.setVisibility(View.GONE); - mSubredditListingViewModel.refresh(); - mAdapter.setNetworkState(null); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingRecyclerViewAdapter.java deleted file mode 100644 index e3669e72..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingRecyclerViewAdapter.java +++ /dev/null @@ -1,226 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.constraintlayout.widget.ConstraintLayout; -import androidx.paging.PagedListAdapter; -import androidx.recyclerview.widget.DiffUtil; -import androidx.recyclerview.widget.RecyclerView; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.bumptech.glide.request.RequestOptions; - -import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditData; -import butterknife.BindView; -import butterknife.ButterKnife; -import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import pl.droidsonroids.gif.GifImageView; -import retrofit2.Retrofit; - -public class SubredditListingRecyclerViewAdapter extends PagedListAdapter { - interface Callback { - void retryLoadingMore(); - void subredditSelected(String subredditName, String iconUrl); - } - - private RequestManager glide; - - private static final int VIEW_TYPE_DATA = 0; - private static final int VIEW_TYPE_ERROR = 1; - private static final int VIEW_TYPE_LOADING = 2; - - private Context context; - private Retrofit oauthRetrofit; - private Retrofit retrofit; - private String accessToken; - private String accountName; - private RedditDataRoomDatabase redditDataRoomDatabase; - - private NetworkState networkState; - private Callback callback; - - SubredditListingRecyclerViewAdapter(Context context, Retrofit oauthRetrofit, Retrofit retrofit, - String accessToken, String accountName, - RedditDataRoomDatabase redditDataRoomDatabase, - Callback callback) { - super(DIFF_CALLBACK); - this.context = context; - this.oauthRetrofit = oauthRetrofit; - this.retrofit = retrofit; - this.accessToken = accessToken; - this.accountName = accountName; - this.redditDataRoomDatabase = redditDataRoomDatabase; - this.callback = callback; - glide = Glide.with(context.getApplicationContext()); - } - - private static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() { - @Override - public boolean areItemsTheSame(@NonNull SubredditData oldItem, @NonNull SubredditData newItem) { - return oldItem.getId().equals(newItem.getId()); - } - - @Override - public boolean areContentsTheSame(@NonNull SubredditData oldItem, @NonNull SubredditData newItem) { - return true; - } - }; - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - if(viewType == VIEW_TYPE_DATA) { - ConstraintLayout constraintLayout = (ConstraintLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_subreddit_listing, parent, false); - return new DataViewHolder(constraintLayout); - } else if(viewType == VIEW_TYPE_ERROR) { - RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_error, parent, false); - return new ErrorViewHolder(relativeLayout); - } else { - RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_loading, parent, false); - return new LoadingViewHolder(relativeLayout); - } - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - if(holder instanceof DataViewHolder) { - SubredditData subredditData = getItem(position); - ((DataViewHolder) holder).constraintLayout.setOnClickListener(view -> - callback.subredditSelected(subredditData.getName(), subredditData.getIconUrl())); - - if(!subredditData.getIconUrl().equals("")) { - glide.load(subredditData.getIconUrl()) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(glide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(((DataViewHolder) holder).iconGifImageView); - } else { - glide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(((DataViewHolder) holder).iconGifImageView); - } - - ((DataViewHolder) holder).subredditNameTextView.setText(subredditData.getName()); - - new CheckIsSubscribedToSubredditAsyncTask(redditDataRoomDatabase, subredditData.getName(), accountName, - new CheckIsSubscribedToSubredditAsyncTask.CheckIsSubscribedToSubredditListener() { - @Override - public void isSubscribed() { - ((DataViewHolder) holder).subscribeButton.setVisibility(View.GONE); - } - - @Override - public void isNotSubscribed() { - ((DataViewHolder) holder).subscribeButton.setVisibility(View.VISIBLE); - ((DataViewHolder) holder).subscribeButton.setOnClickListener(view -> { - SubredditSubscription.subscribeToSubreddit(oauthRetrofit, retrofit, - accessToken, accountName, subredditData.getName(), redditDataRoomDatabase, - new SubredditSubscription.SubredditSubscriptionListener() { - @Override - public void onSubredditSubscriptionSuccess() { - ((DataViewHolder) holder).subscribeButton.setVisibility(View.GONE); - Toast.makeText(context, R.string.subscribed, Toast.LENGTH_SHORT).show(); - } - - @Override - public void onSubredditSubscriptionFail() { - Toast.makeText(context, R.string.subscribe_failed, Toast.LENGTH_SHORT).show(); - } - }); - }); - } - }).execute(); - } - } - - @Override - public int getItemViewType(int position) { - // Reached at the end - if (hasExtraRow() && position == getItemCount() - 1) { - if (networkState.getStatus() == NetworkState.Status.LOADING) { - return VIEW_TYPE_LOADING; - } else { - return VIEW_TYPE_ERROR; - } - } else { - return VIEW_TYPE_DATA; - } - } - - @Override - public int getItemCount() { - if(hasExtraRow()) { - return super.getItemCount() + 1; - } - return super.getItemCount(); - } - - private boolean hasExtraRow() { - return networkState != null && networkState.getStatus() != NetworkState.Status.SUCCESS; - } - - void setNetworkState(NetworkState newNetworkState) { - NetworkState previousState = this.networkState; - boolean previousExtraRow = hasExtraRow(); - this.networkState = newNetworkState; - boolean newExtraRow = hasExtraRow(); - if (previousExtraRow != newExtraRow) { - if (previousExtraRow) { - notifyItemRemoved(super.getItemCount()); - } else { - notifyItemInserted(super.getItemCount()); - } - } else if (newExtraRow && !previousState.equals(newNetworkState)) { - notifyItemChanged(getItemCount() - 1); - } - } - - class DataViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.constraint_layout_item_subreddit_listing) ConstraintLayout constraintLayout; - @BindView(R.id.subreddit_icon_gif_image_view_item_subreddit_listing) GifImageView iconGifImageView; - @BindView(R.id.subreddit_name_text_view_item_subreddit_listing) TextView subredditNameTextView; - @BindView(R.id.subscribe_image_view_item_subreddit_listing) ImageView subscribeButton; - - DataViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - } - } - - class ErrorViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.error_text_view_item_footer_error) TextView errorTextView; - @BindView(R.id.retry_button_item_footer_error) Button retryButton; - - ErrorViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - retryButton.setOnClickListener(view -> callback.retryLoadingMore()); - errorTextView.setText(R.string.load_comments_failed); - } - } - - class LoadingViewHolder extends RecyclerView.ViewHolder { - LoadingViewHolder(@NonNull View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - } - } - - @Override - public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { - if(holder instanceof DataViewHolder) { - glide.clear(((DataViewHolder) holder).iconGifImageView); - ((DataViewHolder) holder).subscribeButton.setVisibility(View.GONE); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingViewModel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingViewModel.java index 4c721763..bf68dd82 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingViewModel.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingViewModel.java @@ -45,31 +45,31 @@ public class SubredditListingViewModel extends ViewModel { }); } - LiveData> getSubreddits() { + public LiveData> getSubreddits() { return subreddits; } - LiveData getPaginationNetworkState() { + public LiveData getPaginationNetworkState() { return paginationNetworkState; } - LiveData getInitialLoadingState() { + public LiveData getInitialLoadingState() { return initialLoadingState; } - LiveData hasSubredditLiveData() { + public LiveData hasSubredditLiveData() { return hasSubredditLiveData; } - void refresh() { + public void refresh() { subredditListingDataSourceFactory.getSubredditListingDataSource().invalidate(); } - void retryLoadingMore() { + public void retryLoadingMore() { subredditListingDataSourceFactory.getSubredditListingDataSource().retryLoadingMore(); } - void changeSortType(String sortType) { + public void changeSortType(String sortType) { sortTypeLiveData.postValue(sortType); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditSelectionActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditSelectionActivity.java deleted file mode 100644 index 16054228..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditSelectionActivity.java +++ /dev/null @@ -1,310 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.app.Activity; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.fragment.app.Fragment; - -import com.google.android.material.appbar.AppBarLayout; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import java.util.ArrayList; - -import javax.inject.Inject; -import javax.inject.Named; - -import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditData; -import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditData; -import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserData; -import butterknife.BindView; -import butterknife.ButterKnife; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class SubredditSelectionActivity extends AppCompatActivity { - - static final String EXTRA_EXTRA_CLEAR_SELECTION = "EECS"; - static final String EXTRA_RETURN_SUBREDDIT_NAME = "ERSN"; - static final String EXTRA_RETURN_SUBREDDIT_ICON_URL = "ERSIURL"; - static final String EXTRA_RETURN_SUBREDDIT_IS_USER = "ERSIU"; - - private static final int SUBREDDIT_SEARCH_REQUEST_CODE = 0; - private static final String INSERT_SUBSCRIBED_SUBREDDIT_STATE = "ISSS"; - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - private static final String ACCOUNT_NAME_STATE = "ANS"; - private static final String ACCOUNT_PROFILE_IMAGE_URL = "APIU"; - private static final String FRAGMENT_OUT_STATE = "FOS"; - - @BindView(R.id.appbar_layout_subreddit_selection_activity) AppBarLayout appBarLayout; - @BindView(R.id.toolbar_subreddit_selection_activity) Toolbar toolbar; - - private boolean mNullAccessToken = false; - private String mAccessToken; - private String mAccountName; - private String mAccountProfileImageUrl; - private boolean mInsertSuccess = false; - - private Fragment mFragment; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_subreddit_selection); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - Resources resources = getResources(); - - if(resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { - Window window = getWindow(); - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - - boolean lightNavBar = false; - if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - lightNavBar = true; - } - boolean finalLightNavBar = lightNavBar; - - View decorView = window.getDecorView(); - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { - @Override - void onStateChanged(AppBarLayout appBarLayout, State state) { - if(state == State.COLLAPSED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } else if(state == State.EXPANDED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } - } - }); - - int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); - if (statusBarResourceId > 0) { - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); - params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); - toolbar.setLayoutParams(params); - } - } - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - if(savedInstanceState == null) { - getCurrentAccountAndBindView(); - } else { - mInsertSuccess = savedInstanceState.getBoolean(INSERT_SUBSCRIBED_SUBREDDIT_STATE); - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); - mAccountProfileImageUrl = savedInstanceState.getString(ACCOUNT_PROFILE_IMAGE_URL); - - if(!mNullAccessToken && mAccountName == null) { - getCurrentAccountAndBindView(); - } else { - mFragment = getSupportFragmentManager().getFragment(savedInstanceState, FRAGMENT_OUT_STATE); - getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_subreddit_selection_activity, mFragment).commit(); - } - } - } - - private void getCurrentAccountAndBindView() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - mAccountProfileImageUrl = account.getProfileImageUrl(); - } - bindView(); - }).execute(); - } - - private void bindView() { - loadSubscriptions(); - - mFragment = new SubscribedSubredditsListingFragment(); - Bundle bundle = new Bundle(); - bundle.putString(SubscribedSubredditsListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); - bundle.putString(SubscribedSubredditsListingFragment.EXTRA_ACCOUNT_PROFILE_IMAGE_URL, mAccountProfileImageUrl); - bundle.putBoolean(SubscribedSubredditsListingFragment.EXTRA_IS_SUBREDDIT_SELECTION, true); - if(getIntent().hasExtra(EXTRA_EXTRA_CLEAR_SELECTION)) { - bundle.putBoolean(SubscribedSubredditsListingFragment.EXTRA_EXTRA_CLEAR_SELECTION, - getIntent().getExtras().getBoolean(EXTRA_EXTRA_CLEAR_SELECTION)); - } - mFragment.setArguments(bundle); - getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_subreddit_selection_activity, mFragment).commit(); - } - - private void loadSubscriptions() { - if (!mInsertSuccess) { - FetchSubscribedThing.fetchSubscribedThing(mOauthRetrofit, mAccessToken, mAccountName, null, - new ArrayList<>(), new ArrayList<>(), - new ArrayList<>(), - new FetchSubscribedThing.FetchSubscribedThingListener() { - @Override - public void onFetchSubscribedThingSuccess(ArrayList subscribedSubredditData, - ArrayList subscribedUserData, - ArrayList subredditData) { - new InsertSubscribedThingsAsyncTask( - mRedditDataRoomDatabase, - mAccountName, - subscribedSubredditData, - subscribedUserData, - subredditData, - () -> mInsertSuccess = true).execute(); - } - - @Override - public void onFetchSubscribedThingFail() { - mInsertSuccess = false; - } - }); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.subreddit_selection_activity, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; - case R.id.action_search_subreddit_selection_activity: - Intent intent = new Intent(this, SearchActivity.class); - intent.putExtra(SearchActivity.EXTRA_SEARCH_ONLY_SUBREDDITS, true); - startActivityForResult(intent, SUBREDDIT_SEARCH_REQUEST_CODE); - return true; - } - - return false; - } - - void getSelectedSubreddit(String name, String iconUrl, boolean subredditIsUser) { - Intent returnIntent = new Intent(); - returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_NAME, name); - returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_ICON_URL, iconUrl); - returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_IS_USER, subredditIsUser); - setResult(Activity.RESULT_OK, returnIntent); - finish(); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - if(requestCode == SUBREDDIT_SEARCH_REQUEST_CODE) { - if(resultCode == RESULT_OK) { - String name = data.getStringExtra(SearchActivity.EXTRA_RETURN_SUBREDDIT_NAME); - String iconUrl = data.getStringExtra(SearchActivity.EXTRA_RETURN_SUBREDDIT_ICON_URL); - Intent returnIntent = new Intent(); - returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_NAME, name); - returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_ICON_URL, iconUrl); - returnIntent.putExtra(EXTRA_RETURN_SUBREDDIT_IS_USER, false); - setResult(Activity.RESULT_OK, returnIntent); - finish(); - } - } - super.onActivityResult(requestCode, resultCode, data); - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - if (mFragment != null) { - getSupportFragmentManager().putFragment(outState, FRAGMENT_OUT_STATE, mFragment); - } - outState.putBoolean(INSERT_SUBSCRIBED_SUBREDDIT_STATE, mInsertSuccess); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - outState.putString(ACCOUNT_NAME_STATE, mAccountName); - outState.putString(ACCOUNT_PROFILE_IMAGE_URL, mAccountProfileImageUrl); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditSubscription.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditSubscription.java index 349c6aed..b12ca826 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditSubscription.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditSubscription.java @@ -13,24 +13,24 @@ import retrofit2.Call; import retrofit2.Callback; import retrofit2.Retrofit; -class SubredditSubscription { - interface SubredditSubscriptionListener { +public class SubredditSubscription { + public interface SubredditSubscriptionListener { void onSubredditSubscriptionSuccess(); void onSubredditSubscriptionFail(); } - static void subscribeToSubreddit(Retrofit oauthRetrofit, Retrofit retrofit, - String accessToken, String subredditName, String accountName, - RedditDataRoomDatabase redditDataRoomDatabase, - SubredditSubscriptionListener subredditSubscriptionListener) { + public static void subscribeToSubreddit(Retrofit oauthRetrofit, Retrofit retrofit, + String accessToken, String subredditName, String accountName, + RedditDataRoomDatabase redditDataRoomDatabase, + SubredditSubscriptionListener subredditSubscriptionListener) { subredditSubscription(oauthRetrofit, retrofit, accessToken, subredditName, accountName, "sub", redditDataRoomDatabase, subredditSubscriptionListener); } - static void unsubscribeToSubreddit(Retrofit oauthRetrofit, String accessToken, - String subredditName, String accountName, - RedditDataRoomDatabase redditDataRoomDatabase, - SubredditSubscriptionListener subredditSubscriptionListener) { + public static void unsubscribeToSubreddit(Retrofit oauthRetrofit, String accessToken, + String subredditName, String accountName, + RedditDataRoomDatabase redditDataRoomDatabase, + SubredditSubscriptionListener subredditSubscriptionListener) { subredditSubscription(oauthRetrofit, null, accessToken, subredditName, accountName, "unsub", redditDataRoomDatabase,subredditSubscriptionListener); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedSubredditsListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedSubredditsListingFragment.java deleted file mode 100644 index d5954501..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedSubredditsListingFragment.java +++ /dev/null @@ -1,116 +0,0 @@ -package ml.docilealligator.infinityforreddit; - - -import android.app.Activity; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.LinearLayout; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProvider; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; - -import javax.inject.Inject; - -import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditViewModel; -import butterknife.BindView; -import butterknife.ButterKnife; - - -/** - * A simple {@link Fragment} subclass. - */ -public class SubscribedSubredditsListingFragment extends Fragment { - - static final String EXTRA_ACCOUNT_NAME = "EAT"; - static final String EXTRA_ACCOUNT_PROFILE_IMAGE_URL = "EAPIU"; - static final String EXTRA_IS_SUBREDDIT_SELECTION = "EISS"; - static final String EXTRA_EXTRA_CLEAR_SELECTION = "EECS"; - - @BindView(R.id.recycler_view_subscribed_subreddits_listing_fragment) RecyclerView mRecyclerView; - @BindView(R.id.no_subscriptions_linear_layout_subreddits_listing_fragment) LinearLayout mLinearLayout; - @BindView(R.id.no_subscriptions_image_view_subreddits_listing_fragment) ImageView mImageView; - - private Activity mActivity; - - private RequestManager mGlide; - - private SubscribedSubredditViewModel mSubscribedSubredditViewModel; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - public SubscribedSubredditsListingFragment() { - // Required empty public constructor - } - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_subscribed_subreddits_listing, container, false); - - ButterKnife.bind(this, rootView); - - mActivity = getActivity(); - - ((Infinity) mActivity.getApplication()).getAppComponent().inject(this); - - Resources resources = getResources(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { - int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); - if (navBarResourceId > 0) { - mRecyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); - } - } - } - - String accountName = getArguments().getString(EXTRA_ACCOUNT_NAME); - - mGlide = Glide.with(this); - - mRecyclerView.setLayoutManager(new LinearLayoutManager(mActivity)); - - SubscribedSubredditsRecyclerViewAdapter adapter; - if(getArguments().getBoolean(EXTRA_IS_SUBREDDIT_SELECTION)) { - adapter = new SubscribedSubredditsRecyclerViewAdapter(mActivity, getArguments().getBoolean(EXTRA_EXTRA_CLEAR_SELECTION), - (name, iconUrl, subredditIsUser) -> ((SubredditSelectionActivity) mActivity).getSelectedSubreddit(name, iconUrl, subredditIsUser)); - } else { - adapter = new SubscribedSubredditsRecyclerViewAdapter(mActivity); - } - - mRecyclerView.setAdapter(adapter); - - mSubscribedSubredditViewModel = new ViewModelProvider(this, - new SubscribedSubredditViewModel.Factory(mActivity.getApplication(), mRedditDataRoomDatabase, accountName)) - .get(SubscribedSubredditViewModel.class); - mSubscribedSubredditViewModel.getAllSubscribedSubreddits().observe(this, subscribedSubredditData -> { - if (subscribedSubredditData == null || subscribedSubredditData.size() == 0) { - mRecyclerView.setVisibility(View.GONE); - mLinearLayout.setVisibility(View.VISIBLE); - mGlide.load(R.drawable.error_image).into(mImageView); - } else { - mLinearLayout.setVisibility(View.GONE); - mRecyclerView.setVisibility(View.VISIBLE); - mGlide.clear(mImageView); - } - - adapter.addUser(accountName, getArguments().getString(EXTRA_ACCOUNT_PROFILE_IMAGE_URL)); - adapter.setSubscribedSubreddits(subscribedSubredditData); - }); - - return rootView; - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedSubredditsRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedSubredditsRecyclerViewAdapter.java deleted file mode 100644 index 897b811d..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedSubredditsRecyclerViewAdapter.java +++ /dev/null @@ -1,152 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Context; -import android.content.Intent; -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 com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.bumptech.glide.request.RequestOptions; - -import java.util.List; - -import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditData; -import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import pl.droidsonroids.gif.GifImageView; - -class SubscribedSubredditsRecyclerViewAdapter extends RecyclerView.Adapter { - private Context mContext; - private List mSubscribedSubredditData; - private RequestManager glide; - private ItemClickListener itemClickListener; - - private String username; - private String userIconUrl; - private boolean hasClearSelectionRow; - - interface ItemClickListener { - void onClick(String name, String iconUrl, boolean subredditIsUser); - } - - SubscribedSubredditsRecyclerViewAdapter(Context context) { - mContext = context; - glide = Glide.with(context.getApplicationContext()); - } - - SubscribedSubredditsRecyclerViewAdapter(Context context, boolean hasClearSelectionRow, ItemClickListener itemClickListener) { - mContext = context; - this.hasClearSelectionRow = hasClearSelectionRow; - glide = Glide.with(context.getApplicationContext()); - this.itemClickListener = itemClickListener; - } - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { - return new SubredditViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_subscribed_thing, viewGroup, false)); - } - - @Override - public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, final int i) { - String name; - String iconUrl; - - if(itemClickListener != null) { - if(hasClearSelectionRow) { - if(viewHolder.getAdapterPosition() == 0) { - ((SubredditViewHolder) viewHolder).subredditNameTextView.setText(R.string.all_subreddits); - viewHolder.itemView.setOnClickListener(view -> itemClickListener.onClick(null, null, false)); - return; - } else if(viewHolder.getAdapterPosition() == 1) { - name = username; - iconUrl = userIconUrl; - viewHolder.itemView.setOnClickListener(view -> itemClickListener.onClick(name, iconUrl, true)); - } else { - name = mSubscribedSubredditData.get(viewHolder.getAdapterPosition() - 2).getName(); - iconUrl = mSubscribedSubredditData.get(viewHolder.getAdapterPosition() - 2).getIconUrl(); - viewHolder.itemView.setOnClickListener(view -> itemClickListener.onClick(name, iconUrl, false)); - } - } else { - if(viewHolder.getAdapterPosition() == 0) { - name = username; - iconUrl = userIconUrl; - viewHolder.itemView.setOnClickListener(view -> itemClickListener.onClick(name, iconUrl, true)); - } else { - name = mSubscribedSubredditData.get(viewHolder.getAdapterPosition() - 1).getName(); - iconUrl = mSubscribedSubredditData.get(viewHolder.getAdapterPosition() - 1).getIconUrl(); - viewHolder.itemView.setOnClickListener(view -> itemClickListener.onClick(name, iconUrl, false)); - } - } - } else { - name = mSubscribedSubredditData.get(viewHolder.getAdapterPosition()).getName(); - iconUrl = mSubscribedSubredditData.get(viewHolder.getAdapterPosition()).getIconUrl(); - - viewHolder.itemView.setOnClickListener(view -> { - Intent intent = new Intent(mContext, ViewSubredditDetailActivity.class); - intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, name); - mContext.startActivity(intent); - }); - } - - if(iconUrl != null && !iconUrl.equals("")) { - glide.load(iconUrl) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(glide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(((SubredditViewHolder) viewHolder).iconGifImageView); - } else { - glide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(((SubredditViewHolder) viewHolder).iconGifImageView); - } - ((SubredditViewHolder) viewHolder).subredditNameTextView.setText(name); - } - - @Override - public int getItemCount() { - if(mSubscribedSubredditData != null) { - if(itemClickListener != null) { - if(hasClearSelectionRow) { - return mSubscribedSubredditData.size() + 2; - } else { - return mSubscribedSubredditData.size() + 1; - } - } - - return mSubscribedSubredditData.size(); - } - return 0; - } - - @Override - public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { - glide.clear(((SubredditViewHolder) holder).iconGifImageView); - } - - void setSubscribedSubreddits(List subscribedSubreddits){ - mSubscribedSubredditData = subscribedSubreddits; - notifyDataSetChanged(); - } - - void addUser(String username, String userIconUrl) { - this.username = username; - this.userIconUrl = userIconUrl; - } - - private class SubredditViewHolder extends RecyclerView.ViewHolder { - private final GifImageView iconGifImageView; - private final TextView subredditNameTextView; - - SubredditViewHolder(View itemView) { - super(itemView); - iconGifImageView = itemView.findViewById(R.id.subreddit_icon_gif_image_view_item_subscribed_subreddit); - subredditNameTextView = itemView.findViewById(R.id.subreddit_name_text_view_item_subscribed_subreddit); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedThingListingActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedThingListingActivity.java deleted file mode 100644 index f45b5f32..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedThingListingActivity.java +++ /dev/null @@ -1,303 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.os.Bundle; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentPagerAdapter; -import androidx.viewpager.widget.ViewPager; - -import com.google.android.material.appbar.AppBarLayout; -import com.google.android.material.tabs.TabLayout; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import java.util.ArrayList; - -import javax.inject.Inject; -import javax.inject.Named; - -import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditData; -import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditData; -import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserData; -import butterknife.BindView; -import butterknife.ButterKnife; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class SubscribedThingListingActivity extends AppCompatActivity { - - private static final String INSERT_SUBSCRIBED_SUBREDDIT_STATE = "ISSS"; - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - private static final String ACCOUNT_NAME_STATE = "ANS"; - - @BindView(R.id.appbar_layout_subscribed_thing_listing_activity) AppBarLayout appBarLayout; - @BindView(R.id.toolbar_subscribed_thing_listing_activity) Toolbar toolbar; - @BindView(R.id.tab_layout_subscribed_thing_listing_activity) TabLayout tabLayout; - @BindView(R.id.view_pager_subscribed_thing_listing_activity) ViewPager viewPager; - - private boolean mNullAccessToken = false; - private String mAccessToken; - private String mAccountName; - private boolean mInsertSuccess = false; - - private SectionsPagerAdapter sectionsPagerAdapter; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_subscribed_thing_listing); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - Resources resources = getResources(); - - if(resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { - Window window = getWindow(); - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - - boolean lightNavBar = false; - if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - lightNavBar = true; - } - boolean finalLightNavBar = lightNavBar; - - View decorView = window.getDecorView(); - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { - @Override - void onStateChanged(AppBarLayout appBarLayout, State state) { - if(state == State.COLLAPSED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } else if(state == State.EXPANDED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } - } - }); - - int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); - if (statusBarResourceId > 0) { - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); - params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); - toolbar.setLayoutParams(params); - } - } - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - if(savedInstanceState != null) { - mInsertSuccess = savedInstanceState.getBoolean(INSERT_SUBSCRIBED_SUBREDDIT_STATE); - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); - if(!mNullAccessToken && mAccessToken == null) { - getCurrentAccountAndInitializeViewPager(); - } else { - initializeViewPagerAndLoadSubscriptions(); - } - } else { - getCurrentAccountAndInitializeViewPager(); - } - } - - private void getCurrentAccountAndInitializeViewPager() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - } - initializeViewPagerAndLoadSubscriptions(); - }).execute(); - } - - private void initializeViewPagerAndLoadSubscriptions() { - sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); - viewPager.setAdapter(sectionsPagerAdapter); - viewPager.setOffscreenPageLimit(2); - tabLayout.setupWithViewPager(viewPager); - - loadSubscriptions(); - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if(item.getItemId() == android.R.id.home) { - finish(); - return true; - } - - return false; - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean(INSERT_SUBSCRIBED_SUBREDDIT_STATE, mInsertSuccess); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - outState.putString(ACCOUNT_NAME_STATE, mAccountName); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - private void loadSubscriptions() { - if (!mInsertSuccess) { - FetchSubscribedThing.fetchSubscribedThing(mOauthRetrofit, mAccessToken, mAccountName, null, - new ArrayList<>(), new ArrayList<>(), - new ArrayList<>(), - new FetchSubscribedThing.FetchSubscribedThingListener() { - @Override - public void onFetchSubscribedThingSuccess(ArrayList subscribedSubredditData, - ArrayList subscribedUserData, - ArrayList subredditData) { - new InsertSubscribedThingsAsyncTask( - mRedditDataRoomDatabase, - mAccountName, - subscribedSubredditData, - subscribedUserData, - subredditData, - () -> mInsertSuccess = true).execute(); - } - - @Override - public void onFetchSubscribedThingFail() { - mInsertSuccess = false; - } - }); - } - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - finish(); - } - - private class SectionsPagerAdapter extends FragmentPagerAdapter { - - public SectionsPagerAdapter(FragmentManager fm) { - super(fm); - } - - @NonNull - @Override - public Fragment getItem(int position) { - switch (position) { - case 0: { - SubscribedSubredditsListingFragment fragment = new SubscribedSubredditsListingFragment(); - Bundle bundle = new Bundle(); - bundle.putBoolean(SubscribedSubredditsListingFragment.EXTRA_IS_SUBREDDIT_SELECTION, false); - bundle.putString(SubscribedSubredditsListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); - fragment.setArguments(bundle); - return fragment; - } - default: - { - FollowedUsersListingFragment fragment = new FollowedUsersListingFragment(); - Bundle bundle = new Bundle(); - bundle.putString(FollowedUsersListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); - fragment.setArguments(bundle); - return fragment; - } - } - } - - @Override - public int getCount() { - return 2; - } - - @Override - public CharSequence getPageTitle(int position) { - switch (position) { - case 0: - return getString(R.string.subreddits); - case 1: - return getString(R.string.users); - } - - return null; - } - - @NonNull - @Override - public Object instantiateItem(@NonNull ViewGroup container, int position) { - return super.instantiateItem(container, position); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SwitchAccountAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SwitchAccountAsyncTask.java deleted file mode 100644 index 65801464..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SwitchAccountAsyncTask.java +++ /dev/null @@ -1,36 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.AsyncTask; - -import ml.docilealligator.infinityforreddit.Account.Account; - -class SwitchAccountAsyncTask extends AsyncTask { - interface SwitchAccountAsyncTaskListener { - void switched(Account account); - } - - private RedditDataRoomDatabase redditDataRoomDatabase; - private String newAccountName; - private Account account; - private SwitchAccountAsyncTaskListener switchAccountAsyncTaskListener; - - SwitchAccountAsyncTask(RedditDataRoomDatabase redditDataRoomDatabase, String newAccountName, - SwitchAccountAsyncTaskListener switchAccountAsyncTaskListener) { - this.redditDataRoomDatabase = redditDataRoomDatabase; - this.newAccountName = newAccountName; - this.switchAccountAsyncTaskListener = switchAccountAsyncTaskListener; - } - - @Override - protected Void doInBackground(Void... voids) { - redditDataRoomDatabase.accountDao().markAllAccountsNonCurrent(); - redditDataRoomDatabase.accountDao().markAccountCurrent(newAccountName); - account = redditDataRoomDatabase.accountDao().getCurrentAccount(); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - switchAccountAsyncTaskListener.switched(account); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SwitchAccountEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SwitchAccountEvent.java deleted file mode 100644 index 82b73d73..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SwitchAccountEvent.java +++ /dev/null @@ -1,9 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -public class SwitchAccountEvent { - String excludeActivityClassName; - public SwitchAccountEvent() {} - public SwitchAccountEvent(String excludeActivityClassName) { - this.excludeActivityClassName = excludeActivityClassName; - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SwitchToAnonymousAccountAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SwitchToAnonymousAccountAsyncTask.java deleted file mode 100644 index 588131dd..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SwitchToAnonymousAccountAsyncTask.java +++ /dev/null @@ -1,37 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.AsyncTask; - -import ml.docilealligator.infinityforreddit.Account.AccountDao; - -class SwitchToAnonymousAccountAsyncTask extends AsyncTask { - interface SwitchToAnonymousAccountAsyncTaskListener { - void logoutSuccess(); - } - - private RedditDataRoomDatabase redditDataRoomDatabase; - private boolean removeCurrentAccount; - private SwitchToAnonymousAccountAsyncTaskListener switchToAnonymousAccountAsyncTaskListener; - - SwitchToAnonymousAccountAsyncTask(RedditDataRoomDatabase redditDataRoomDatabase, boolean removeCurrentAccount, - SwitchToAnonymousAccountAsyncTaskListener switchToAnonymousAccountAsyncTaskListener) { - this.redditDataRoomDatabase = redditDataRoomDatabase; - this.removeCurrentAccount = removeCurrentAccount; - this.switchToAnonymousAccountAsyncTaskListener = switchToAnonymousAccountAsyncTaskListener; - } - - @Override - protected Void doInBackground(Void... voids) { - AccountDao accountDao = redditDataRoomDatabase.accountDao(); - if(removeCurrentAccount) { - accountDao.deleteCurrentAccount(); - } - accountDao.markAllAccountsNonCurrent(); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - switchToAnonymousAccountAsyncTaskListener.logoutSuccess(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/UserFollowing.java b/app/src/main/java/ml/docilealligator/infinityforreddit/UserFollowing.java index 201e2ce0..f4743db5 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/UserFollowing.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/UserFollowing.java @@ -14,24 +14,24 @@ import retrofit2.Call; import retrofit2.Callback; import retrofit2.Retrofit; -class UserFollowing { - interface UserFollowingListener { +public class UserFollowing { + public interface UserFollowingListener { void onUserFollowingSuccess(); void onUserFollowingFail(); } - static void followUser(Retrofit oauthRetrofit, Retrofit retrofit, - String accessToken, String username, String accountName, - SubscribedUserDao subscribedUserDao, - UserFollowingListener userFollowingListener) { + public static void followUser(Retrofit oauthRetrofit, Retrofit retrofit, + String accessToken, String username, String accountName, + SubscribedUserDao subscribedUserDao, + UserFollowingListener userFollowingListener) { userFollowing(oauthRetrofit, retrofit, accessToken, username, accountName, "sub", subscribedUserDao, userFollowingListener); } - static void unfollowUser(Retrofit oauthRetrofit, Retrofit retrofit, - String accessToken, String username, String accountName, - SubscribedUserDao subscribedUserDao, - UserFollowingListener userFollowingListener) { + public static void unfollowUser(Retrofit oauthRetrofit, Retrofit retrofit, + String accessToken, String username, String accountName, + SubscribedUserDao subscribedUserDao, + UserFollowingListener userFollowingListener) { userFollowing(oauthRetrofit, retrofit, accessToken, username, accountName, "unsub", subscribedUserDao, userFollowingListener); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingFragment.java deleted file mode 100644 index ed62f453..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingFragment.java +++ /dev/null @@ -1,159 +0,0 @@ -package ml.docilealligator.infinityforreddit; - - -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProvider; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.bumptech.glide.Glide; -import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import retrofit2.Retrofit; - - -/** - * A simple {@link Fragment} subclass. - */ -public class UserListingFragment extends Fragment implements FragmentCommunicator { - - static final String EXTRA_QUERY = "EQ"; - static final String EXTRA_ACCESS_TOKEN = "EAT"; - static final String EXTRA_ACCOUNT_NAME = "EAN"; - - @BindView(R.id.coordinator_layout_user_listing_fragment) CoordinatorLayout mCoordinatorLayout; - @BindView(R.id.recycler_view_user_listing_fragment) RecyclerView mUserListingRecyclerView; - @BindView(R.id.progress_bar_user_listing_fragment) CircleProgressBar mProgressBar; - @BindView(R.id.fetch_user_listing_info_linear_layout_user_listing_fragment) LinearLayout mFetchUserListingInfoLinearLayout; - @BindView(R.id.fetch_user_listing_info_image_view_user_listing_fragment) ImageView mFetchUserListingInfoImageView; - @BindView(R.id.fetch_user_listing_info_text_view_user_listing_fragment) TextView mFetchUserListingInfoTextView; - - private LinearLayoutManager mLinearLayoutManager; - - private String mQuery; - - private UserListingRecyclerViewAdapter mAdapter; - - UserListingViewModel mUserListingViewModel; - - @Inject @Named("no_oauth") - Retrofit mRetrofit; - - @Inject @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase redditDataRoomDatabase; - - public UserListingFragment() { - // Required empty public constructor - } - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - // Inflate the layout for this fragment - View rootView = inflater.inflate(R.layout.fragment_user_listing, container, false); - - ((Infinity) getActivity().getApplication()).getAppComponent().inject(this); - - ButterKnife.bind(this, rootView); - - Resources resources = getResources(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { - int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); - if (navBarResourceId > 0) { - mUserListingRecyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); - } - } - } - - mLinearLayoutManager = new LinearLayoutManager(getActivity()); - mUserListingRecyclerView.setLayoutManager(mLinearLayoutManager); - - mQuery = getArguments().getString(EXTRA_QUERY); - String accessToken = getArguments().getString(EXTRA_ACCESS_TOKEN); - String accountName = getArguments().getString(EXTRA_ACCOUNT_NAME); - - mAdapter = new UserListingRecyclerViewAdapter(getActivity(), mOauthRetrofit, mRetrofit, - accessToken, accountName, redditDataRoomDatabase.subscribedUserDao(), - () -> mUserListingViewModel.retryLoadingMore()); - - mUserListingRecyclerView.setAdapter(mAdapter); - - UserListingViewModel.Factory factory = new UserListingViewModel.Factory(mRetrofit, mQuery, - PostDataSource.SORT_TYPE_RELEVANCE); - mUserListingViewModel = new ViewModelProvider(this, factory).get(UserListingViewModel.class); - mUserListingViewModel.getUsers().observe(this, UserData -> mAdapter.submitList(UserData)); - - mUserListingViewModel.hasUser().observe(this, hasUser -> { - mProgressBar.setVisibility(View.GONE); - if(hasUser) { - mFetchUserListingInfoLinearLayout.setVisibility(View.GONE); - } else { - mFetchUserListingInfoLinearLayout.setOnClickListener(view -> { - //Do nothing - }); - showErrorView(R.string.no_users); - } - }); - - mUserListingViewModel.getInitialLoadingState().observe(this, networkState -> { - if(networkState.getStatus().equals(NetworkState.Status.SUCCESS)) { - mProgressBar.setVisibility(View.GONE); - } else if(networkState.getStatus().equals(NetworkState.Status.FAILED)) { - mProgressBar.setVisibility(View.GONE); - mFetchUserListingInfoLinearLayout.setOnClickListener(view -> refresh()); - showErrorView(R.string.search_users_error); - } else { - mProgressBar.setVisibility(View.VISIBLE); - } - }); - - mUserListingViewModel.getPaginationNetworkState().observe(this, networkState -> { - mAdapter.setNetworkState(networkState); - }); - - return rootView; - } - - private void showErrorView(int stringResId) { - if(getActivity() != null && isAdded()) { - mProgressBar.setVisibility(View.GONE); - mFetchUserListingInfoLinearLayout.setVisibility(View.VISIBLE); - mFetchUserListingInfoTextView.setText(stringResId); - Glide.with(this).load(R.drawable.error_image).into(mFetchUserListingInfoImageView); - } - } - - void changeSortType(String sortType) { - mUserListingViewModel.changeSortType(sortType); - } - - @Override - public void refresh() { - mFetchUserListingInfoLinearLayout.setVisibility(View.GONE); - mUserListingViewModel.refresh(); - mAdapter.setNetworkState(null); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingRecyclerViewAdapter.java deleted file mode 100644 index 2a8f53df..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingRecyclerViewAdapter.java +++ /dev/null @@ -1,229 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Context; -import android.content.Intent; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.constraintlayout.widget.ConstraintLayout; -import androidx.paging.PagedListAdapter; -import androidx.recyclerview.widget.DiffUtil; -import androidx.recyclerview.widget.RecyclerView; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.bumptech.glide.request.RequestOptions; - -import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserDao; -import ml.docilealligator.infinityforreddit.User.UserData; -import butterknife.BindView; -import butterknife.ButterKnife; -import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import pl.droidsonroids.gif.GifImageView; -import retrofit2.Retrofit; - -public class UserListingRecyclerViewAdapter extends PagedListAdapter { - interface RetryLoadingMoreCallback { - void retryLoadingMore(); - } - - private RequestManager glide; - - private static final int VIEW_TYPE_DATA = 0; - private static final int VIEW_TYPE_ERROR = 1; - private static final int VIEW_TYPE_LOADING = 2; - - private Context context; - private Retrofit oauthRetrofit; - private Retrofit retrofit; - private String accessToken; - private String accountName; - private SubscribedUserDao subscribedUserDao; - - private NetworkState networkState; - private UserListingRecyclerViewAdapter.RetryLoadingMoreCallback retryLoadingMoreCallback; - - UserListingRecyclerViewAdapter(Context context, Retrofit oauthRetrofit, Retrofit retrofit, - String accessToken, String accountName, SubscribedUserDao subscribedUserDao, - UserListingRecyclerViewAdapter.RetryLoadingMoreCallback retryLoadingMoreCallback) { - super(DIFF_CALLBACK); - this.context = context; - this.oauthRetrofit = oauthRetrofit; - this.retrofit = retrofit; - this.accessToken = accessToken; - this.accountName = accountName; - this.subscribedUserDao = subscribedUserDao; - this.retryLoadingMoreCallback = retryLoadingMoreCallback; - glide = Glide.with(context.getApplicationContext()); - } - - private static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() { - @Override - public boolean areItemsTheSame(@NonNull UserData oldItem, @NonNull UserData newItem) { - return oldItem.getName().equals(newItem.getName()); - } - - @Override - public boolean areContentsTheSame(@NonNull UserData oldItem, @NonNull UserData newItem) { - return true; - } - }; - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - if(viewType == VIEW_TYPE_DATA) { - ConstraintLayout constraintLayout = (ConstraintLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_user_listing, parent, false); - return new UserListingRecyclerViewAdapter.DataViewHolder(constraintLayout); - } else if(viewType == VIEW_TYPE_ERROR) { - RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_error, parent, false); - return new UserListingRecyclerViewAdapter.ErrorViewHolder(relativeLayout); - } else { - RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_loading, parent, false); - return new UserListingRecyclerViewAdapter.LoadingViewHolder(relativeLayout); - } - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - if(holder instanceof UserListingRecyclerViewAdapter.DataViewHolder) { - UserData userData = getItem(position); - ((UserListingRecyclerViewAdapter.DataViewHolder) holder).constraintLayout.setOnClickListener(view -> { - Intent intent = new Intent(context, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, userData.getName()); - context.startActivity(intent); - }); - - if(!userData.getIconUrl().equals("")) { - glide.load(userData.getIconUrl()) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(glide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(((UserListingRecyclerViewAdapter.DataViewHolder) holder).iconGifImageView); - } else { - glide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(((UserListingRecyclerViewAdapter.DataViewHolder) holder).iconGifImageView); - } - - ((UserListingRecyclerViewAdapter.DataViewHolder) holder).UserNameTextView.setText(userData.getName()); - - new CheckIsFollowingUserAsyncTask(subscribedUserDao, userData.getName(), accountName, - new CheckIsFollowingUserAsyncTask.CheckIsFollowingUserListener() { - @Override - public void isSubscribed() { - ((UserListingRecyclerViewAdapter.DataViewHolder) holder).subscribeButton.setVisibility(View.GONE); - } - - @Override - public void isNotSubscribed() { - ((UserListingRecyclerViewAdapter.DataViewHolder) holder).subscribeButton.setVisibility(View.VISIBLE); - ((UserListingRecyclerViewAdapter.DataViewHolder) holder).subscribeButton.setOnClickListener(view -> { - UserFollowing.followUser(oauthRetrofit, retrofit, - accessToken, userData.getName(), accountName, subscribedUserDao, - new UserFollowing.UserFollowingListener() { - @Override - public void onUserFollowingSuccess() { - ((UserListingRecyclerViewAdapter.DataViewHolder) holder).subscribeButton.setVisibility(View.GONE); - Toast.makeText(context, R.string.followed, Toast.LENGTH_SHORT).show(); - } - - @Override - public void onUserFollowingFail() { - Toast.makeText(context, R.string.follow_failed, Toast.LENGTH_SHORT).show(); - } - }); - }); - } - }).execute(); - } - } - - @Override - public int getItemViewType(int position) { - // Reached at the end - if (hasExtraRow() && position == getItemCount() - 1) { - if (networkState.getStatus() == NetworkState.Status.LOADING) { - return VIEW_TYPE_LOADING; - } else { - return VIEW_TYPE_ERROR; - } - } else { - return VIEW_TYPE_DATA; - } - } - - @Override - public int getItemCount() { - if(hasExtraRow()) { - return super.getItemCount() + 1; - } - return super.getItemCount(); - } - - private boolean hasExtraRow() { - return networkState != null && networkState.getStatus() != NetworkState.Status.SUCCESS; - } - - void setNetworkState(NetworkState newNetworkState) { - NetworkState previousState = this.networkState; - boolean previousExtraRow = hasExtraRow(); - this.networkState = newNetworkState; - boolean newExtraRow = hasExtraRow(); - if (previousExtraRow != newExtraRow) { - if (previousExtraRow) { - notifyItemRemoved(super.getItemCount()); - } else { - notifyItemInserted(super.getItemCount()); - } - } else if (newExtraRow && !previousState.equals(newNetworkState)) { - notifyItemChanged(getItemCount() - 1); - } - } - - class DataViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.constraint_layout_item_user_listing) ConstraintLayout constraintLayout; - @BindView(R.id.user_icon_gif_image_view_item_user_listing) GifImageView iconGifImageView; - @BindView(R.id.user_name_text_view_item_user_listing) TextView UserNameTextView; - @BindView(R.id.subscribe_image_view_item_user_listing) ImageView subscribeButton; - - DataViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - } - } - - class ErrorViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.error_text_view_item_footer_error) TextView errorTextView; - @BindView(R.id.retry_button_item_footer_error) Button retryButton; - - ErrorViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - retryButton.setOnClickListener(view -> retryLoadingMoreCallback.retryLoadingMore()); - errorTextView.setText(R.string.load_comments_failed); - } - } - - class LoadingViewHolder extends RecyclerView.ViewHolder { - LoadingViewHolder(@NonNull View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - } - } - - @Override - public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { - if(holder instanceof UserListingRecyclerViewAdapter.DataViewHolder) { - glide.clear(((UserListingRecyclerViewAdapter.DataViewHolder) holder).iconGifImageView); - ((UserListingRecyclerViewAdapter.DataViewHolder) holder).subscribeButton.setVisibility(View.GONE); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingViewModel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingViewModel.java index 03c72ec2..70f53ebc 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingViewModel.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/UserListingViewModel.java @@ -45,31 +45,31 @@ public class UserListingViewModel extends ViewModel { }); } - LiveData> getUsers() { + public LiveData> getUsers() { return users; } - LiveData getPaginationNetworkState() { + public LiveData getPaginationNetworkState() { return paginationNetworkState; } - LiveData getInitialLoadingState() { + public LiveData getInitialLoadingState() { return initialLoadingState; } - LiveData hasUser() { + public LiveData hasUser() { return hasUserLiveData; } - void refresh() { + public void refresh() { userListingDataSourceFactory.getUserListingDataSource().invalidate(); } - void retryLoadingMore() { + public void retryLoadingMore() { userListingDataSourceFactory.getUserListingDataSource().retryLoadingMore(); } - void changeSortType(String sortType) { + public void changeSortType(String sortType) { sortTypeLiveData.postValue(sortType); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/UserThingSortTypeBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/UserThingSortTypeBottomSheetFragment.java deleted file mode 100644 index dfbf297e..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/UserThingSortTypeBottomSheetFragment.java +++ /dev/null @@ -1,88 +0,0 @@ -package ml.docilealligator.infinityforreddit; - - -import android.app.Activity; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; - -import com.deishelon.roundedbottomsheet.RoundedBottomSheetDialogFragment; - -import butterknife.BindView; -import butterknife.ButterKnife; - - -/** - * A simple {@link Fragment} subclass. - */ -public class UserThingSortTypeBottomSheetFragment extends RoundedBottomSheetDialogFragment { - - interface UserThingSortTypeSelectionCallback { - void userThingSortTypeSelected(String sortType); - } - - static final String EXTRA_NO_BEST_TYPE = "ENBT"; - - @BindView(R.id.new_type_text_view_user_thing_sort_type_bottom_sheet_fragment) TextView newTypeTextView; - @BindView(R.id.hot_type_text_view_user_thing_sort_type_bottom_sheet_fragment) TextView hotTypeTextView; - @BindView(R.id.top_type_text_view_user_thing_sort_type_bottom_sheet_fragment) TextView topTypeTextView; - @BindView(R.id.controversial_type_text_view_user_thing_sort_type_bottom_sheet_fragment) TextView controversialTypeTextView; - - public UserThingSortTypeBottomSheetFragment() { - // Required empty public constructor - } - - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_user_thing_sort_type_bottom_sheet, container, false); - - ButterKnife.bind(this, rootView); - - Activity activity = getActivity(); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O - && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - - newTypeTextView.setOnClickListener(view -> { - if(activity != null) { - ((UserThingSortTypeSelectionCallback) activity).userThingSortTypeSelected(PostDataSource.SORT_TYPE_NEW); - } - dismiss(); - }); - - hotTypeTextView.setOnClickListener(view -> { - if(activity != null) { - ((UserThingSortTypeSelectionCallback) activity).userThingSortTypeSelected(PostDataSource.SORT_TYPE_HOT); - } - dismiss(); - }); - - topTypeTextView.setOnClickListener(view -> { - if(activity != null) { - ((UserThingSortTypeSelectionCallback) activity).userThingSortTypeSelected(PostDataSource.SORT_TYPE_TOP); - } - dismiss(); - }); - - controversialTypeTextView.setOnClickListener(view -> { - if(activity != null) { - ((UserThingSortTypeSelectionCallback) activity).userThingSortTypeSelected(PostDataSource.SORT_TYPE_CONTROVERSIAL); - } - dismiss(); - }); - - return rootView; - } - -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils.java index bdd32364..5d30578e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils.java @@ -1,7 +1,7 @@ package ml.docilealligator.infinityforreddit; -class Utils { - static String addSubredditAndUserLink(String markdown) { +public class Utils { + public static String addSubredditAndUserLink(String markdown) { return markdown.replaceAll("(? { - if(!isSwiping) { - mProgressBar.setVisibility(View.VISIBLE); - mLoadErrorLinearLayout.setVisibility(View.GONE); - loadImage(); - } - }); - - float pxHeight = getResources().getDisplayMetrics().heightPixels; - - int activityColorFrom = getResources().getColor(android.R.color.black); - int actionBarColorFrom = getResources().getColor(R.color.transparentActionBarAndExoPlayerControllerColor); - int actionBarElementColorFrom = getResources().getColor(android.R.color.white); - int colorTo = getResources().getColor(android.R.color.transparent); - - final ValueAnimator activityColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), activityColorFrom, colorTo); - final ValueAnimator actionBarColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), actionBarColorFrom, colorTo); - final ValueAnimator actionBarElementColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), actionBarElementColorFrom, colorTo); - - activityColorAnimation.setDuration(300); // milliseconds - actionBarColorAnimation.setDuration(300); - actionBarElementColorAnimation.setDuration(300); - - activityColorAnimation.addUpdateListener(valueAnimator -> mRelativeLayout.setBackgroundColor((int) valueAnimator.getAnimatedValue())); - - actionBarColorAnimation.addUpdateListener(valueAnimator -> actionBar.setBackgroundDrawable(new ColorDrawable((int) valueAnimator.getAnimatedValue()))); - - actionBarElementColorAnimation.addUpdateListener(valueAnimator -> { - upArrow.setColorFilter((int) valueAnimator.getAnimatedValue(), PorterDuff.Mode.SRC_IN); - if(mMenu != null) { - Drawable drawable = mMenu.getItem(0).getIcon(); - //drawable.mutate(); - drawable.setColorFilter((int) valueAnimator.getAnimatedValue(), PorterDuff.Mode.SRC_IN); - } - }); - - loadImage(); - - swipe = new Swipe(); - swipe.setListener(new SimpleSwipeListener() { - @Override - public void onSwipingUp(final MotionEvent event) { - isSwiping = true; - float nowY = event.getY(); - float offset; - if (touchY == -1.0f) { - offset = 0.0f; - } else { - offset = nowY - touchY; - } - totalLengthY += offset; - touchY = nowY; - mImageView.animate() - .y(totalLengthY) - .setDuration(0) - .start(); - mLoadErrorLinearLayout.animate() - .y(totalLengthY) - .setDuration(0) - .start(); - } - - @Override - public boolean onSwipedUp(final MotionEvent event) { - if (totalLengthY < -pxHeight / 8) { - mImageView.animate() - .y(-pxHeight) - .setDuration(300) - .setListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animator) { - activityColorAnimation.start(); - actionBarColorAnimation.start(); - actionBarElementColorAnimation.start(); - } - - @Override - public void onAnimationEnd(Animator animator) { - finish(); - } - - @Override - public void onAnimationCancel(Animator animator) { - } - - @Override - public void onAnimationRepeat(Animator animator) { - } - }) - .start(); - mLoadErrorLinearLayout.animate() - .y(-pxHeight) - .setDuration(300) - .start(); - } else { - isSwiping = false; - mImageView.animate() - .y(0) - .setDuration(300) - .start(); - mLoadErrorLinearLayout.animate() - .y(0) - .setDuration(300) - .start(); - } - - totalLengthY = 0.0f; - touchY = -1.0f; - return false; - } - - @Override - public void onSwipingDown(final MotionEvent event) { - isSwiping = true; - float nowY = event.getY(); - float offset; - if (touchY == -1.0f) { - offset = 0.0f; - } else { - offset = nowY - touchY; - } - totalLengthY += offset; - touchY = nowY; - mImageView.animate() - .y(totalLengthY) - .setDuration(0) - .start(); - mLoadErrorLinearLayout.animate() - .y(totalLengthY) - .setDuration(0) - .start(); - } - - @Override - public boolean onSwipedDown(final MotionEvent event) { - if (totalLengthY > pxHeight / 8) { - mImageView.animate() - .y(pxHeight) - .setDuration(300) - .setListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animator) { - activityColorAnimation.start(); - actionBarColorAnimation.start(); - actionBarElementColorAnimation.start(); - } - - @Override - public void onAnimationEnd(Animator animator) { - finish(); - } - - @Override - public void onAnimationCancel(Animator animator) { - } - - @Override - public void onAnimationRepeat(Animator animator) { - } - }) - .start(); - mLoadErrorLinearLayout.animate() - .y(pxHeight) - .setDuration(300) - .start(); - } else { - isSwiping = false; - mImageView.animate() - .y(0) - .setDuration(300) - .start(); - mLoadErrorLinearLayout.animate() - .y(0) - .setDuration(300) - .start(); - } - - totalLengthY = 0.0f; - touchY = -1.0f; - - return false; - } - }); - - mImageView.getController().addOnStateChangeListener(new GestureController.OnStateChangeListener() { - @Override - public void onStateChanged(State state) { - zoom = state.getZoom(); - } - - @Override - public void onStateReset(State oldState, State newState) { - - } - }); - - mImageView.getController().getSettings().setMaxZoom(10f).setDoubleTapZoom(2f).setPanEnabled(true); - - mImageView.setOnClickListener(view -> { - if (isActionBarHidden) { - getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); - isActionBarHidden = false; - } else { - getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_FULLSCREEN - | View.SYSTEM_UI_FLAG_IMMERSIVE); - isActionBarHidden = true; - } - }); - } - - private void loadImage() { - Glide.with(this).load(mImageUrl).listener(new RequestListener() { - @Override - public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { - mProgressBar.setVisibility(View.GONE); - mLoadErrorLinearLayout.setVisibility(View.VISIBLE); - return false; - } - - @Override - public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { - mProgressBar.setVisibility(View.GONE); - return false; - } - }).apply(new RequestOptions().fitCenter()).into(mImageView); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - mMenu = menu; - getMenuInflater().inflate(R.menu.view_image, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; - case R.id.action_download_view_image: - if (isDownloading) { - return false; - } - - isDownloading = true; - - if (Build.VERSION.SDK_INT >= 23) { - if (ContextCompat.checkSelfPermission(this, - Manifest.permission.WRITE_EXTERNAL_STORAGE) - != PackageManager.PERMISSION_GRANTED) { - - // Permission is not granted - // No explanation needed; request the permission - ActivityCompat.requestPermissions(this, - new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE); - } else { - // Permission has already been granted - saveImage(); - } - } else { - saveImage(); - } - - return true; - } - - return false; - } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - if(zoom == 1.0) { - swipe.dispatchTouchEvent(ev); - } - return super.dispatchTouchEvent(ev); - } - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - if(requestCode == PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE && grantResults.length > 0) { - if(grantResults[0] == PackageManager.PERMISSION_DENIED) { - Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show(); - } else if(grantResults[0] == PackageManager.PERMISSION_GRANTED && isDownloading) { - saveImage(); - } - isDownloading = false; - } - } - - private void saveImage() { - DownloadManager.Request request = new DownloadManager.Request(Uri.parse(mImageUrl)); - request.setTitle(mImageFileName); - - request.allowScanningByMediaScanner(); - request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); - - //Android Q support - if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - request.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES, mImageFileName); - } else { - String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString(); - File directory = new File(path + "/Infinity/"); - boolean saveToInfinityFolder = true; - if(!directory.exists()) { - if(!directory.mkdir()) { - saveToInfinityFolder = false; - } - } else { - if(directory.isFile()) { - if(!(directory.delete() && directory.mkdir())) { - saveToInfinityFolder = false; - } - } - } - - if(saveToInfinityFolder) { - request.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES + "/Infinity/", mImageFileName); - } else { - request.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES, mImageFileName); - } - } - - DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); - - if(manager == null) { - Toast.makeText(this, R.string.download_failed, Toast.LENGTH_SHORT).show(); - return; - } - - manager.enqueue(request); - Toast.makeText(this, R.string.download_started, Toast.LENGTH_SHORT).show(); - } - - @Override - protected void onPause() { - super.onPause(); - overridePendingTransition(0, 0); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewMessageActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewMessageActivity.java deleted file mode 100644 index fd45795d..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewMessageActivity.java +++ /dev/null @@ -1,318 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.lifecycle.ViewModelProvider; -import androidx.recyclerview.widget.DividerItemDecoration; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.google.android.material.appbar.AppBarLayout; -import com.google.android.material.appbar.CollapsingToolbarLayout; -import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class ViewMessageActivity extends AppCompatActivity { - - static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; - - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - private static final String NEW_ACCOUNT_NAME_STATE = "NANS"; - - @BindView(R.id.collapsing_toolbar_layout_view_message_activity) CollapsingToolbarLayout collapsingToolbarLayout; - @BindView(R.id.appbar_layout_view_message_activity) AppBarLayout appBarLayout; - @BindView(R.id.toolbar_view_message_activity) Toolbar toolbar; - @BindView(R.id.progress_bar_view_message_activity) CircleProgressBar mProgressBar; - @BindView(R.id.recycler_view_view_message_activity) RecyclerView recyclerView; - @BindView(R.id.fetch_messages_info_linear_layout_view_message_activity) LinearLayout mFetchMessageInfoLinearLayout; - @BindView(R.id.fetch_messages_info_image_view_view_message_activity) ImageView mFetchMessageInfoImageView; - @BindView(R.id.fetch_messages_info_text_view_view_message_activity) TextView mFetchMessageInfoTextView; - - private boolean mNullAccessToken = false; - private String mAccessToken; - private String mNewAccountName; - - private MessageRecyclerViewAdapter mAdapter; - - private RequestManager mGlide; - - MessageViewModel mMessageViewModel; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_view_message); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - mGlide = Glide.with(this); - - Resources resources = getResources(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 - && (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT - || resources.getBoolean(R.bool.isTablet))) { - Window window = getWindow(); - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - - boolean lightNavBar = false; - if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - lightNavBar = true; - } - boolean finalLightNavBar = lightNavBar; - - View decorView = window.getDecorView(); - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { - @Override - void onStateChanged(AppBarLayout appBarLayout, State state) { - if (state == State.COLLAPSED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } else if (state == State.EXPANDED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } - } - }); - - int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); - if (statusBarResourceId > 0) { - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); - params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); - toolbar.setLayoutParams(params); - } - - int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); - if (navBarResourceId > 0) { - recyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); - } - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - toolbar.setTitle(R.string.inbox); - setSupportActionBar(toolbar); - - if(savedInstanceState != null) { - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - mNewAccountName = savedInstanceState.getString(NEW_ACCOUNT_NAME_STATE); - - if(!mNullAccessToken && mAccessToken == null) { - getCurrentAccountAndFetchMessage(); - } else { - bindView(); - } - } else { - mNewAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); - getCurrentAccountAndFetchMessage(); - } - } - - private void getCurrentAccountAndFetchMessage() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(mNewAccountName != null) { - if(account == null || !account.getUsername().equals(mNewAccountName)) { - new SwitchAccountAsyncTask(mRedditDataRoomDatabase, mNewAccountName, newAccount -> { - EventBus.getDefault().post(new SwitchAccountEvent(getClass().getName())); - Toast.makeText(this, R.string.account_switched, Toast.LENGTH_SHORT).show(); - - mNewAccountName = null; - if(newAccount == null) { - mNullAccessToken = true; - } else { - mAccessToken = newAccount.getAccessToken(); - } - - bindView(); - }).execute(); - } else { - mAccessToken = account.getAccessToken(); - bindView(); - } - } else { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - } - - bindView(); - } - }).execute(); - } - - private void bindView() { - mAdapter = new MessageRecyclerViewAdapter(this, mOauthRetrofit, mAccessToken, - () -> mMessageViewModel.retryLoadingMore()); - LinearLayoutManager layoutManager = new LinearLayoutManager(this); - recyclerView.setLayoutManager(layoutManager); - recyclerView.setAdapter(mAdapter); - DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this, layoutManager.getOrientation()); - recyclerView.addItemDecoration(dividerItemDecoration); - - MessageViewModel.Factory factory = new MessageViewModel.Factory(mOauthRetrofit, - getResources().getConfiguration().locale, mAccessToken, FetchMessages.WHERE_INBOX); - mMessageViewModel = new ViewModelProvider(this, factory).get(MessageViewModel.class); - mMessageViewModel.getMessages().observe(this, messages -> mAdapter.submitList(messages)); - - mMessageViewModel.hasMessage().observe(this, hasMessage -> { - mProgressBar.setVisibility(View.GONE); - if(hasMessage) { - mFetchMessageInfoLinearLayout.setVisibility(View.GONE); - } else { - mFetchMessageInfoLinearLayout.setOnClickListener(view -> { - //Do nothing - }); - showErrorView(R.string.no_messages); - } - }); - - mMessageViewModel.getInitialLoadingState().observe(this, networkState -> { - if(networkState.getStatus().equals(NetworkState.Status.SUCCESS)) { - mProgressBar.setVisibility(View.GONE); - } else if(networkState.getStatus().equals(NetworkState.Status.FAILED)) { - mProgressBar.setVisibility(View.GONE); - mFetchMessageInfoLinearLayout.setOnClickListener(view -> { - mFetchMessageInfoLinearLayout.setVisibility(View.GONE); - mMessageViewModel.refresh(); - mAdapter.setNetworkState(null); - }); - showErrorView(R.string.load_messages_failed); - } else { - mProgressBar.setVisibility(View.VISIBLE); - } - }); - - mMessageViewModel.getPaginationNetworkState().observe(this, networkState -> { - mAdapter.setNetworkState(networkState); - }); - } - - private void showErrorView(int stringResId) { - mProgressBar.setVisibility(View.GONE); - mFetchMessageInfoLinearLayout.setVisibility(View.VISIBLE); - mFetchMessageInfoTextView.setText(stringResId); - mGlide.load(R.drawable.error_image).into(mFetchMessageInfoImageView); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.view_message_activity, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if(item.getItemId() == R.id.action_refresh_view_message_activity) { - mMessageViewModel.refresh(); - mAdapter.setNetworkState(null); - return true; - } else if(item.getItemId() == android.R.id.home) { - finish(); - return true; - } - return false; - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - outState.putString(NEW_ACCOUNT_NAME_STATE, mNewAccountName); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - if(!getClass().getName().equals(event.excludeActivityClassName)) { - finish(); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java deleted file mode 100644 index 91855a0d..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java +++ /dev/null @@ -1,1290 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.evernote.android.state.State; -import com.google.android.material.appbar.AppBarLayout; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import com.google.android.material.snackbar.Snackbar; -import com.livefront.bridge.Bridge; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import javax.inject.Inject; -import javax.inject.Named; - -import butterknife.BindView; -import butterknife.ButterKnife; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; -import static ml.docilealligator.infinityforreddit.CommentActivity.EXTRA_COMMENT_DATA_KEY; -import static ml.docilealligator.infinityforreddit.CommentActivity.WRITE_COMMENT_REQUEST_CODE; - -public class ViewPostDetailActivity extends AppCompatActivity implements FlairBottomSheetFragment.FlairSelectionCallback { - - static final String EXTRA_POST_DATA = "EPD"; - static final String EXTRA_POST_LIST_POSITION = "EPLI"; - static final String EXTRA_POST_ID = "EPI"; - static final String EXTRA_SINGLE_COMMENT_ID = "ESCI"; - static final String EXTRA_MESSAGE_FULLNAME = "ENI"; - static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; - - private static final int EDIT_POST_REQUEST_CODE = 2; - static final int EDIT_COMMENT_REQUEST_CODE = 3; - - private RequestManager mGlide; - private Locale mLocale; - private Menu mMenu; - - private int orientation; - private int postListPosition = -1; - private String mSingleCommentId; - private boolean mNeedBlurNsfw; - private boolean mNeedBlurSpoiler; - - @State - boolean mNullAccessToken = false; - @State - String mAccessToken; - @State - String mAccountName; - @State - Post mPost; - @State - boolean isLoadingMoreChildren = false; - @State - boolean isRefreshing = false; - @State - boolean isSingleCommentThreadMode = false; - @State - ArrayList comments; - @State - ArrayList children; - @State - int mChildrenStartingIndex = 0; - @State - boolean loadMoreChildrenSuccess = true; - @State - boolean hasMoreChildren; - @State - String mMessageFullname; - @State - String mNewAccountName; - - private boolean showToast = false; - - private LinearLayoutManager mLinearLayoutManager; - private CommentAndPostRecyclerViewAdapter mAdapter; - - @BindView(R.id.coordinator_layout_view_post_detail) CoordinatorLayout mCoordinatorLayout; - @BindView(R.id.appbar_layout_view_post_detail_activity) AppBarLayout appBarLayout; - @BindView(R.id.toolbar_view_post_detail_activity) Toolbar toolbar; - @BindView(R.id.progress_bar_view_post_detail_activity) ProgressBar mProgressBar; - @BindView(R.id.recycler_view_view_post_detail) RecyclerView mRecyclerView; - @BindView(R.id.fetch_post_info_linear_layout_view_post_detail_activity) LinearLayout mFetchPostInfoLinearLayout; - @BindView(R.id.fetch_post_info_image_view_view_post_detail_activity) ImageView mFetchPostInfoImageView; - @BindView(R.id.fetch_post_info_text_view_view_post_detail_activity) TextView mFetchPostInfoTextView; - - @Inject @Named("no_oauth") - Retrofit mRetrofit; - - @Inject @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_view_post_detail); - - Bridge.restoreInstanceState(this, savedInstanceState); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - Resources resources = getResources(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 - && (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT - || resources.getBoolean(R.bool.isTablet))) { - Window window = getWindow(); - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - - boolean lightNavBar = false; - if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - lightNavBar = true; - } - boolean finalLightNavBar = lightNavBar; - - View decorView = window.getDecorView(); - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { - @Override - void onStateChanged(AppBarLayout appBarLayout, State state) { - if (state == State.COLLAPSED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } else if (state == State.EXPANDED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } - } - }); - - int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); - if (statusBarResourceId > 0) { - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); - params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); - toolbar.setLayoutParams(params); - } - - int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); - if (navBarResourceId > 0) { - mRecyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); - showToast = true; - } - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - toolbar.setTitle(""); - setSupportActionBar(toolbar); - - mNeedBlurNsfw = mSharedPreferences.getBoolean(SharedPreferencesUtils.BLUR_NSFW_KEY, true); - mNeedBlurSpoiler = mSharedPreferences.getBoolean(SharedPreferencesUtils.BLUR_SPOILER_KEY, false); - - mGlide = Glide.with(this); - mLocale = getResources().getConfiguration().locale; - - mLinearLayoutManager = new LinearLayoutManager(this); - mRecyclerView.setLayoutManager(mLinearLayoutManager); - - mSingleCommentId = getIntent().hasExtra(EXTRA_SINGLE_COMMENT_ID) ? getIntent().getExtras().getString(EXTRA_SINGLE_COMMENT_ID) : null; - if(savedInstanceState == null) { - if(mSingleCommentId != null) { - isSingleCommentThreadMode = true; - } - mMessageFullname = getIntent().getStringExtra(EXTRA_MESSAGE_FULLNAME); - mNewAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); - } - - orientation = getResources().getConfiguration().orientation; - - if(!mNullAccessToken && mAccessToken == null) { - getCurrentAccountAndBindView(); - } else { - bindView(); - } - - if(getIntent().hasExtra(EXTRA_POST_LIST_POSITION)) { - postListPosition = getIntent().getIntExtra(EXTRA_POST_LIST_POSITION, -1); - } - } - - private void getCurrentAccountAndBindView() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(mNewAccountName != null) { - if(account == null || !account.getUsername().equals(mNewAccountName)) { - new SwitchAccountAsyncTask(mRedditDataRoomDatabase, mNewAccountName, newAccount -> { - EventBus.getDefault().post(new SwitchAccountEvent(getClass().getName())); - Toast.makeText(this, R.string.account_switched, Toast.LENGTH_SHORT).show(); - - mNewAccountName = null; - if(newAccount == null) { - mNullAccessToken = true; - } else { - mAccessToken = newAccount.getAccessToken(); - mAccountName = newAccount.getUsername(); - } - - bindView(); - }).execute(); - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - bindView(); - } - } else { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - } - - bindView(); - } - }).execute(); - } - - private void bindView() { - if(mAccessToken != null && mMessageFullname != null) { - ReadMessage.readMessage(mOauthRetrofit, mAccessToken, mMessageFullname, new ReadMessage.ReadMessageListener() { - @Override - public void readSuccess() { - mMessageFullname = null; - } - - @Override - public void readFailed() { - - } - }); - } - - if(mPost == null) { - mPost = getIntent().getParcelableExtra(EXTRA_POST_DATA); - } - - if(mPost == null) { - fetchPostAndCommentsById(getIntent().getStringExtra(EXTRA_POST_ID)); - } else { - if(mMenu != null) { - MenuItem saveItem = mMenu.findItem(R.id.action_save_view_post_detail_activity); - MenuItem hideItem = mMenu.findItem(R.id.action_hide_view_post_detail_activity); - - mMenu.findItem(R.id.action_comment_view_post_detail_activity).setVisible(true); - - if(mAccessToken != null) { - if(mPost.isSaved()) { - saveItem.setVisible(true); - saveItem.setIcon(R.drawable.ic_baseline_bookmark_24px); - } else { - saveItem.setVisible(true); - saveItem.setIcon(R.drawable.ic_baseline_bookmark_border_24px); - } - - if(mPost.isHidden()) { - hideItem.setVisible(true); - hideItem.setTitle(R.string.action_unhide_post); - } else { - hideItem.setVisible(true); - hideItem.setTitle(R.string.action_hide_post); - } - } else { - saveItem.setVisible(false); - hideItem.setVisible(false); - } - - if(mPost.getAuthor().equals(mAccountName)) { - if(mPost.getPostType() == Post.TEXT_TYPE) { - mMenu.findItem(R.id.action_edit_view_post_detail_activity).setVisible(true); - } - mMenu.findItem(R.id.action_delete_view_post_detail_activity).setVisible(true); - - MenuItem nsfwItem = mMenu.findItem(R.id.action_nsfw_view_post_detail_activity); - nsfwItem.setVisible(true); - if(mPost.isNSFW()) { - nsfwItem.setTitle(R.string.action_unmark_nsfw); - } else { - nsfwItem.setTitle(R.string.action_mark_nsfw); - } - - MenuItem spoilerItem = mMenu.findItem(R.id.action_spoiler_view_post_detail_activity); - spoilerItem.setVisible(true); - if(mPost.isSpoiler()) { - spoilerItem.setTitle(R.string.action_unmark_spoiler); - } else { - spoilerItem.setTitle(R.string.action_mark_spoiler); - } - - mMenu.findItem(R.id.action_edit_flair_view_post_detail_activity).setVisible(true); - } - - mMenu.findItem(R.id.action_view_crosspost_parent_view_post_detail_activity).setVisible(mPost.getCrosspostParentId() != null); - } - - mAdapter = new CommentAndPostRecyclerViewAdapter(ViewPostDetailActivity.this, mRetrofit, - mOauthRetrofit, mRedditDataRoomDatabase, mGlide, mAccessToken, mAccountName, mPost, - mLocale, mSingleCommentId, isSingleCommentThreadMode, mNeedBlurNsfw, mNeedBlurSpoiler, - new CommentAndPostRecyclerViewAdapter.CommentRecyclerViewAdapterCallback() { - @Override - public void updatePost(Post post) { - EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); - } - - @Override - public void retryFetchingComments() { - fetchComments(false); - } - - @Override - public void retryFetchingMoreComments() { - isLoadingMoreChildren = false; - loadMoreChildrenSuccess = true; - - fetchMoreComments(); - } - }); - mRecyclerView.setAdapter(mAdapter); - - if(comments == null) { - fetchComments(false); - } else { - if(isRefreshing) { - isRefreshing = false; - refresh(true, true); - } else { - mAdapter.addComments(comments, hasMoreChildren); - if(isLoadingMoreChildren) { - isLoadingMoreChildren = false; - fetchMoreComments(); - } - } - } - } - } - - - private void fetchPostAndCommentsById(String subredditId) { - mFetchPostInfoLinearLayout.setVisibility(View.GONE); - mProgressBar.setVisibility(View.VISIBLE); - mGlide.clear(mFetchPostInfoImageView); - - Call postAndComments; - if(mAccessToken == null) { - if(isSingleCommentThreadMode && mSingleCommentId != null) { - postAndComments = mRetrofit.create(RedditAPI.class).getPostAndCommentsSingleThreadById(subredditId, mSingleCommentId); - } else { - postAndComments = mRetrofit.create(RedditAPI.class).getPostAndCommentsById(subredditId); - } - } else { - if(isSingleCommentThreadMode && mSingleCommentId != null) { - postAndComments = mOauthRetrofit.create(RedditAPI.class).getPostAndCommentsSingleThreadByIdOauth(subredditId, - mSingleCommentId, RedditUtils.getOAuthHeader(mAccessToken)); - } else { - postAndComments = mOauthRetrofit.create(RedditAPI.class).getPostAndCommentsByIdOauth(subredditId, - RedditUtils.getOAuthHeader(mAccessToken)); - } - } - postAndComments.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - mProgressBar.setVisibility(View.GONE); - - if(response.isSuccessful()) { - ParsePost.parsePost(response.body(), mLocale, new ParsePost.ParsePostListener() { - @Override - public void onParsePostSuccess(Post post) { - mPost = post; - - if(mMenu != null) { - MenuItem saveItem = mMenu.findItem(R.id.action_save_view_post_detail_activity); - MenuItem hideItem = mMenu.findItem(R.id.action_hide_view_post_detail_activity); - - mMenu.findItem(R.id.action_comment_view_post_detail_activity).setVisible(true); - - if(mAccessToken != null) { - if(post.isSaved()) { - saveItem.setVisible(true); - saveItem.setIcon(R.drawable.ic_baseline_bookmark_24px); - } else { - saveItem.setVisible(true); - saveItem.setIcon(R.drawable.ic_baseline_bookmark_border_24px); - } - - if(post.isHidden()) { - hideItem.setVisible(true); - hideItem.setTitle(R.string.action_unhide_post); - } else { - hideItem.setVisible(true); - hideItem.setTitle(R.string.action_hide_post); - } - } else { - saveItem.setVisible(false); - hideItem.setVisible(false); - } - - if(mPost.getAuthor().equals(mAccountName)) { - if(mPost.getPostType() == Post.TEXT_TYPE) { - mMenu.findItem(R.id.action_edit_view_post_detail_activity).setVisible(true); - } - mMenu.findItem(R.id.action_delete_view_post_detail_activity).setVisible(true); - } - - mMenu.findItem(R.id.action_view_crosspost_parent_view_post_detail_activity).setVisible(mPost.getCrosspostParentId() != null); - } - - mAdapter = new CommentAndPostRecyclerViewAdapter(ViewPostDetailActivity.this, - mRetrofit, mOauthRetrofit, mRedditDataRoomDatabase, mGlide, - mAccessToken, mAccountName, mPost, mLocale, mSingleCommentId, - isSingleCommentThreadMode, mNeedBlurNsfw, mNeedBlurSpoiler, - new CommentAndPostRecyclerViewAdapter.CommentRecyclerViewAdapterCallback() { - @Override - public void updatePost(Post post) { - EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); - } - - @Override - public void retryFetchingComments() { - fetchComments(false); - } - - @Override - public void retryFetchingMoreComments() { - isLoadingMoreChildren = false; - loadMoreChildrenSuccess = true; - - fetchMoreComments(); - } - }); - mRecyclerView.setAdapter(mAdapter); - - ParseComment.parseComment(response.body(), new ArrayList<>(), mLocale, - new ParseComment.ParseCommentListener() { - @Override - public void onParseCommentSuccess(ArrayList expandedComments, String parentId, ArrayList moreChildrenFullnames) { - ViewPostDetailActivity.this.children = moreChildrenFullnames; - - hasMoreChildren = children.size() != 0; - mAdapter.addComments(expandedComments, hasMoreChildren); - - if(children.size() > 0) { - mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { - super.onScrolled(recyclerView, dx, dy); - - if(!isLoadingMoreChildren && loadMoreChildrenSuccess) { - int visibleItemCount = mLinearLayoutManager.getChildCount(); - int totalItemCount = mLinearLayoutManager.getItemCount(); - int firstVisibleItemPosition = mLinearLayoutManager.findFirstVisibleItemPosition(); - - if ((visibleItemCount + firstVisibleItemPosition >= totalItemCount) && firstVisibleItemPosition >= 0) { - fetchMoreComments(); - } - } - } - }); - } - } - - @Override - public void onParseCommentFailed() { - mAdapter.initiallyLoadCommentsFailed(); - } - }); - } - - @Override - public void onParsePostFail() { - showErrorView(subredditId); - } - }); - } else { - showErrorView(subredditId); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - showErrorView(subredditId); - } - }); - } - - private void fetchComments(boolean changeRefreshState) { - mAdapter.setSingleComment(mSingleCommentId, isSingleCommentThreadMode); - mAdapter.initiallyLoading(); - String commentId = null; - if(isSingleCommentThreadMode) { - commentId = mSingleCommentId; - } - - Retrofit retrofit = mAccessToken == null ? mRetrofit : mOauthRetrofit; - FetchComment.fetchComments(retrofit, mAccessToken, mPost.getId(), commentId, mLocale, new FetchComment.FetchCommentListener() { - @Override - public void onFetchCommentSuccess(ArrayList expandedComments, - String parentId, ArrayList children) { - ViewPostDetailActivity.this.children = children; - - comments = expandedComments; - hasMoreChildren = children.size() != 0; - mAdapter.addComments(expandedComments, hasMoreChildren); - - if(children.size() > 0) { - mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { - super.onScrolled(recyclerView, dx, dy); - - if(!isLoadingMoreChildren && loadMoreChildrenSuccess) { - int visibleItemCount = mLinearLayoutManager.getChildCount(); - int totalItemCount = mLinearLayoutManager.getItemCount(); - int firstVisibleItemPosition = mLinearLayoutManager.findFirstVisibleItemPosition(); - - if ((visibleItemCount + firstVisibleItemPosition >= totalItemCount) && firstVisibleItemPosition >= 0) { - fetchMoreComments(); - } - } - } - }); - } - if(changeRefreshState) { - isRefreshing = false; - } - } - - @Override - public void onFetchCommentFailed() { - mAdapter.initiallyLoadCommentsFailed(); - if(changeRefreshState) { - isRefreshing = false; - } - } - }); - } - - void fetchMoreComments() { - if(isLoadingMoreChildren || !loadMoreChildrenSuccess) { - return; - } - - isLoadingMoreChildren = true; - - Retrofit retrofit = mAccessToken == null ? mRetrofit : mOauthRetrofit; - FetchComment.fetchMoreComment(retrofit, mAccessToken, children, mChildrenStartingIndex, - 0, mLocale, new FetchComment.FetchMoreCommentListener() { - @Override - public void onFetchMoreCommentSuccess(ArrayList expandedComments, int childrenStartingIndex) { - hasMoreChildren = childrenStartingIndex < children.size(); - mAdapter.addComments(expandedComments, hasMoreChildren); - mChildrenStartingIndex = childrenStartingIndex; - isLoadingMoreChildren = false; - loadMoreChildrenSuccess = true; - } - - @Override - public void onFetchMoreCommentFailed() { - isLoadingMoreChildren = false; - loadMoreChildrenSuccess = false; - mAdapter.loadMoreCommentsFailed(); - } - }); - } - - private void refresh(boolean fetchPost, boolean fetchComments) { - if(!isRefreshing) { - isRefreshing = true; - mChildrenStartingIndex = 0; - - mFetchPostInfoLinearLayout.setVisibility(View.GONE); - mGlide.clear(mFetchPostInfoImageView); - - if(fetchComments) { - if(!fetchPost) { - fetchComments(true); - } else { - fetchComments(false); - } - } - - if(fetchPost) { - Retrofit retrofit; - if(mAccessToken == null) { - retrofit = mRetrofit; - } else { - retrofit = mOauthRetrofit; - } - FetchPost.fetchPost(retrofit, mPost.getId(), mAccessToken, mLocale, - new FetchPost.FetchPostListener() { - @Override - public void fetchPostSuccess(Post post) { - mPost = post; - mAdapter.updatePost(mPost); - EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); - isRefreshing = false; - if(mMenu != null) { - MenuItem saveItem = mMenu.findItem(R.id.action_save_view_post_detail_activity); - MenuItem hideItem = mMenu.findItem(R.id.action_hide_view_post_detail_activity); - - mMenu.findItem(R.id.action_comment_view_post_detail_activity).setVisible(true); - - if(mAccessToken != null) { - if(post.isSaved()) { - saveItem.setVisible(true); - saveItem.setIcon(R.drawable.ic_baseline_bookmark_24px); - } else { - saveItem.setVisible(true); - saveItem.setIcon(R.drawable.ic_baseline_bookmark_border_24px); - } - - if(post.isHidden()) { - hideItem.setVisible(true); - hideItem.setTitle(R.string.action_unhide_post); - } else { - hideItem.setVisible(true); - hideItem.setTitle(R.string.action_hide_post); - } - } else { - saveItem.setVisible(false); - hideItem.setVisible(false); - } - - mMenu.findItem(R.id.action_view_crosspost_parent_view_post_detail_activity).setVisible(mPost.getCrosspostParentId() != null); - } - } - - @Override - public void fetchPostFailed() { - showMessage(R.string.refresh_post_failed); - isRefreshing = false; - } - }); - } - } - } - - private void showErrorView(String subredditId) { - mProgressBar.setVisibility(View.GONE); - mFetchPostInfoLinearLayout.setVisibility(View.VISIBLE); - mFetchPostInfoLinearLayout.setOnClickListener(view -> fetchPostAndCommentsById(subredditId)); - mFetchPostInfoTextView.setText(R.string.load_post_error); - mGlide.load(R.drawable.error_image).into(mFetchPostInfoImageView); - } - - private void showMessage(int resId) { - if(showToast) { - Toast.makeText(ViewPostDetailActivity.this, resId, Toast.LENGTH_SHORT).show(); - } else { - Snackbar.make(mCoordinatorLayout, resId, Snackbar.LENGTH_SHORT).show(); - } - } - - private void markNSFW() { - if(mMenu != null) { - mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_unmark_nsfw); - } - - Map params = new HashMap<>(); - params.put(RedditUtils.ID_KEY, mPost.getFullName()); - mOauthRetrofit.create(RedditAPI.class).markNSFW(RedditUtils.getOAuthHeader(mAccessToken), params) - .enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if(response.isSuccessful()) { - if(mMenu != null) { - mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_unmark_nsfw); - } - - refresh(true, false); - showMessage(R.string.mark_nsfw_success); - } else { - if(mMenu != null) { - mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_mark_nsfw); - } - - showMessage(R.string.mark_nsfw_failed); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - if(mMenu != null) { - mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_mark_nsfw); - } - - showMessage(R.string.mark_nsfw_failed); - } - }); - } - - private void unmarkNSFW() { - if(mMenu != null) { - mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_mark_nsfw); - } - - Map params = new HashMap<>(); - params.put(RedditUtils.ID_KEY, mPost.getFullName()); - mOauthRetrofit.create(RedditAPI.class).unmarkNSFW(RedditUtils.getOAuthHeader(mAccessToken), params) - .enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if(response.isSuccessful()) { - if(mMenu != null) { - mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_mark_nsfw); - } - - refresh(true, false); - showMessage(R.string.unmark_nsfw_success); - } else { - if(mMenu != null) { - mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_unmark_nsfw); - } - - showMessage(R.string.unmark_nsfw_failed); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - if(mMenu != null) { - mMenu.findItem(R.id.action_nsfw_view_post_detail_activity).setTitle(R.string.action_unmark_nsfw); - } - - showMessage(R.string.unmark_nsfw_failed); - } - }); - } - - private void markSpoiler() { - if(mMenu != null) { - mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_unmark_spoiler); - } - - Map params = new HashMap<>(); - params.put(RedditUtils.ID_KEY, mPost.getFullName()); - mOauthRetrofit.create(RedditAPI.class).markSpoiler(RedditUtils.getOAuthHeader(mAccessToken), params) - .enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if(response.isSuccessful()) { - if(mMenu != null) { - mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_unmark_spoiler); - } - - refresh(true, false); - showMessage(R.string.mark_spoiler_success); - } else { - if(mMenu != null) { - mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_mark_spoiler); - } - - showMessage(R.string.mark_spoiler_failed); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - if(mMenu != null) { - mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_mark_spoiler); - } - - showMessage(R.string.mark_spoiler_failed); - } - }); - } - - private void unmarkSpoiler() { - if(mMenu != null) { - mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_mark_spoiler); - } - - Map params = new HashMap<>(); - params.put(RedditUtils.ID_KEY, mPost.getFullName()); - mOauthRetrofit.create(RedditAPI.class).unmarkSpoiler(RedditUtils.getOAuthHeader(mAccessToken), params) - .enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if(response.isSuccessful()) { - if(mMenu != null) { - mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_mark_spoiler); - } - - refresh(true, false); - showMessage(R.string.unmark_spoiler_success); - } else { - if(mMenu != null) { - mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_unmark_spoiler); - } - - showMessage(R.string.unmark_spoiler_failed); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - if(mMenu != null) { - mMenu.findItem(R.id.action_spoiler_view_post_detail_activity).setTitle(R.string.action_unmark_spoiler); - } - - showMessage(R.string.unmark_spoiler_failed); - } - }); - } - - void deleteComment(String fullName, int position) { - new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme) - .setTitle(R.string.delete_this_comment) - .setMessage(R.string.are_you_sure) - .setPositiveButton(R.string.delete, (dialogInterface, i) - -> DeleteThing.delete(mOauthRetrofit, fullName, mAccessToken, new DeleteThing.DeleteThingListener() { - @Override - public void deleteSuccess() { - Toast.makeText(ViewPostDetailActivity.this, R.string.delete_post_success, Toast.LENGTH_SHORT).show(); - mAdapter.deleteComment(position); - } - - @Override - public void deleteFailed() { - Toast.makeText(ViewPostDetailActivity.this, R.string.delete_post_failed, Toast.LENGTH_SHORT).show(); - } - })) - .setNegativeButton(R.string.cancel, null) - .show(); - } - - void changeToSingleThreadMode() { - isSingleCommentThreadMode = false; - mSingleCommentId = null; - refresh(false, true); - } - - @Subscribe - public void onPostUpdateEvent(PostUpdateEventToDetailActivity event) { - if(mPost.getId().equals(event.post.getId())) { - mPost.setVoteType(event.post.getVoteType()); - mPost.setSaved(event.post.isSaved()); - if(mMenu != null) { - if(event.post.isSaved()) { - mMenu.findItem(R.id.action_save_view_post_detail_activity).setIcon(getResources() - .getDrawable(R.drawable.ic_baseline_bookmark_24px)); - } else { - mMenu.findItem(R.id.action_save_view_post_detail_activity).setIcon(getResources() - .getDrawable(R.drawable.ic_baseline_bookmark_border_24px)); - } - } - mAdapter.updatePost(mPost); - } - } - - @Subscribe - public void onChangeNSFWBlurEvent(ChangeNSFWBlurEvent event) { - mAdapter.setBlurNSFW(event.needBlurNSFW); - refreshAdapter(); - } - - @Subscribe - public void onChangeSpoilerBlurEvent(ChangeSpoilerBlurEvent event) { - mAdapter.setBlurSpoiler(event.needBlurSpoiler); - refreshAdapter(); - } - - private void refreshAdapter() { - int previousPosition = -1; - if(mLinearLayoutManager != null) { - previousPosition = mLinearLayoutManager.findFirstVisibleItemPosition(); - } - - RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager(); - mRecyclerView.setAdapter(null); - mRecyclerView.setLayoutManager(null); - mRecyclerView.setAdapter(mAdapter); - mRecyclerView.setLayoutManager(layoutManager); - - if(previousPosition > 0) { - mRecyclerView.scrollToPosition(previousPosition); - } - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - if(!getClass().getName().equals(event.excludeActivityClassName)) { - finish(); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.view_post_detail_activity, menu); - mMenu = menu; - if(mPost != null) { - MenuItem saveItem = mMenu.findItem(R.id.action_save_view_post_detail_activity); - MenuItem hideItem = mMenu.findItem(R.id.action_hide_view_post_detail_activity); - - mMenu.findItem(R.id.action_comment_view_post_detail_activity).setVisible(true); - - if(mAccessToken != null) { - if(mPost.isSaved()) { - saveItem.setVisible(true); - saveItem.setIcon(R.drawable.ic_baseline_bookmark_24px); - } else { - saveItem.setVisible(true); - saveItem.setIcon(R.drawable.ic_baseline_bookmark_border_24px); - } - - if(mPost.isHidden()) { - hideItem.setVisible(true); - hideItem.setTitle(R.string.action_unhide_post); - } else { - hideItem.setVisible(true); - hideItem.setTitle(R.string.action_hide_post); - } - } else { - saveItem.setVisible(false); - hideItem.setVisible(false); - } - - if(mPost.getAuthor().equals(mAccountName)) { - if(mPost.getPostType() == Post.TEXT_TYPE) { - menu.findItem(R.id.action_edit_view_post_detail_activity).setVisible(true); - } - menu.findItem(R.id.action_delete_view_post_detail_activity).setVisible(true); - - MenuItem nsfwItem = menu.findItem(R.id.action_nsfw_view_post_detail_activity); - nsfwItem.setVisible(true); - if(mPost.isNSFW()) { - nsfwItem.setTitle(R.string.action_unmark_nsfw); - } else { - nsfwItem.setTitle(R.string.action_mark_nsfw); - } - - MenuItem spoilerItem = menu.findItem(R.id.action_spoiler_view_post_detail_activity); - spoilerItem.setVisible(true); - if(mPost.isSpoiler()) { - spoilerItem.setTitle(R.string.action_unmark_spoiler); - } else { - spoilerItem.setTitle(R.string.action_mark_spoiler); - } - - menu.findItem(R.id.action_edit_flair_view_post_detail_activity).setVisible(true); - } - - menu.findItem(R.id.action_view_crosspost_parent_view_post_detail_activity).setVisible(mPost.getCrosspostParentId() != null); - } - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case R.id.action_refresh_view_post_detail_activity: - refresh(true, true); - return true; - case R.id.action_comment_view_post_detail_activity: - if(mPost != null) { - if(mPost.isArchived()) { - showMessage(R.string.archived_post_reply_unavailable); - return true; - } - - if(mPost.isLocked()) { - showMessage(R.string.locked_post_comment_unavailable); - return true; - } - - if(mAccessToken == null) { - showMessage(R.string.login_first); - return true; - } - - Intent intent = new Intent(this, CommentActivity.class); - intent.putExtra(CommentActivity.EXTRA_COMMENT_PARENT_TEXT_KEY, mPost.getTitle()); - intent.putExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY, mPost.getFullName()); - intent.putExtra(CommentActivity.EXTRA_PARENT_DEPTH_KEY, 0); - intent.putExtra(CommentActivity.EXTRA_IS_REPLYING_KEY, false); - startActivityForResult(intent, WRITE_COMMENT_REQUEST_CODE); - } - return true; - case R.id.action_save_view_post_detail_activity: - if(mPost != null && mAccessToken != null) { - if(mPost.isSaved()) { - item.setIcon(R.drawable.ic_baseline_bookmark_border_24px); - SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, mPost.getFullName(), - new SaveThing.SaveThingListener() { - @Override - public void success() { - mPost.setSaved(false); - item.setIcon(R.drawable.ic_baseline_bookmark_border_24px); - showMessage(R.string.post_unsaved_success); - EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); - } - - @Override - public void failed() { - mPost.setSaved(true); - item.setIcon(R.drawable.ic_baseline_bookmark_24px); - showMessage(R.string.post_unsaved_failed); - EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); - } - }); - } else { - item.setIcon(R.drawable.ic_baseline_bookmark_24px); - SaveThing.saveThing(mOauthRetrofit, mAccessToken, mPost.getFullName(), - new SaveThing.SaveThingListener() { - @Override - public void success() { - mPost.setSaved(true); - item.setIcon(R.drawable.ic_baseline_bookmark_24px); - showMessage(R.string.post_saved_success); - EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); - } - - @Override - public void failed() { - mPost.setSaved(false); - item.setIcon(R.drawable.ic_baseline_bookmark_border_24px); - showMessage(R.string.post_saved_failed); - EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); - } - }); - } - } - return true; - case R.id.action_view_crosspost_parent_view_post_detail_activity: - Intent crosspostIntent = new Intent(this, ViewPostDetailActivity.class); - crosspostIntent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, mPost.getCrosspostParentId()); - startActivity(crosspostIntent); - return true; - case R.id.action_hide_view_post_detail_activity: - if(mPost != null && mAccessToken != null) { - if(mPost.isHidden()) { - item.setTitle(R.string.action_hide_post); - - HidePost.unhidePost(mOauthRetrofit, mAccessToken, mPost.getFullName(), new HidePost.HidePostListener() { - @Override - public void success() { - mPost.setHidden(false); - item.setTitle(R.string.action_hide_post); - showMessage(R.string.post_unhide_success); - EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); - } - - @Override - public void failed() { - mPost.setHidden(true); - item.setTitle(R.string.action_unhide_post); - showMessage(R.string.post_unhide_failed); - EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); - } - }); - } else { - item.setTitle(R.string.action_unhide_post); - - HidePost.hidePost(mOauthRetrofit, mAccessToken, mPost.getFullName(), new HidePost.HidePostListener() { - @Override - public void success() { - mPost.setHidden(true); - item.setTitle(R.string.action_unhide_post); - showMessage(R.string.post_hide_success); - EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); - } - - @Override - public void failed() { - mPost.setHidden(false); - item.setTitle(R.string.action_hide_post); - showMessage(R.string.post_hide_failed); - EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition)); - } - }); - } - } - return true; - case R.id.action_edit_view_post_detail_activity: - Intent editPostItent = new Intent(this, EditPostActivity.class); - editPostItent.putExtra(EditPostActivity.EXTRA_ACCESS_TOKEN, mAccessToken); - editPostItent.putExtra(EditPostActivity.EXTRA_FULLNAME, mPost.getFullName()); - editPostItent.putExtra(EditPostActivity.EXTRA_TITLE, mPost.getTitle()); - editPostItent.putExtra(EditPostActivity.EXTRA_CONTENT, mPost.getSelfText()); - startActivityForResult(editPostItent, EDIT_POST_REQUEST_CODE); - return true; - case R.id.action_delete_view_post_detail_activity: - new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme) - .setTitle(R.string.delete_this_post) - .setMessage(R.string.are_you_sure) - .setPositiveButton(R.string.delete, (dialogInterface, i) - -> DeleteThing.delete(mOauthRetrofit, mPost.getFullName(), mAccessToken, new DeleteThing.DeleteThingListener() { - @Override - public void deleteSuccess() { - Toast.makeText(ViewPostDetailActivity.this, R.string.delete_post_success, Toast.LENGTH_SHORT).show(); - finish(); - } - - @Override - public void deleteFailed() { - showMessage(R.string.delete_post_failed); - } - })) - .setNegativeButton(R.string.cancel, null) - .show(); - return true; - case R.id.action_nsfw_view_post_detail_activity: - if(mPost.isNSFW()) { - unmarkNSFW(); - } else { - markNSFW(); - } - return true; - case R.id.action_spoiler_view_post_detail_activity: - if(mPost.isSpoiler()) { - unmarkSpoiler(); - } else { - markSpoiler(); - } - return true; - case R.id.action_edit_flair_view_post_detail_activity: - FlairBottomSheetFragment flairBottomSheetFragment = new FlairBottomSheetFragment(); - Bundle bundle = new Bundle(); - bundle.putString(FlairBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - bundle.putString(FlairBottomSheetFragment.EXTRA_SUBREDDIT_NAME, mPost.getSubredditName()); - flairBottomSheetFragment.setArguments(bundle); - flairBottomSheetFragment.show(getSupportFragmentManager(), flairBottomSheetFragment.getTag()); - return true; - case android.R.id.home: - onBackPressed(); - return true; - } - return false; - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if(requestCode == WRITE_COMMENT_REQUEST_CODE) { - if(data != null && resultCode == RESULT_OK) { - if(data.hasExtra(EXTRA_COMMENT_DATA_KEY)) { - CommentData comment = data.getParcelableExtra(EXTRA_COMMENT_DATA_KEY); - if(comment != null && comment.getDepth() == 0) { - mAdapter.addComment(comment); - } else { - String parentFullname = data.getStringExtra(CommentActivity.EXTRA_PARENT_FULLNAME_KEY); - int parentPosition = data.getIntExtra(CommentActivity.EXTRA_PARENT_POSITION_KEY, -1); - if(parentFullname != null && parentPosition >= 0) { - mAdapter.addChildComment(comment, parentFullname, parentPosition); - } - } - } else { - Toast.makeText(this, R.string.send_comment_failed, Toast.LENGTH_SHORT).show(); - } - } - } else if(requestCode == EDIT_POST_REQUEST_CODE) { - if(resultCode == RESULT_OK) { - refresh(true, false); - } - } else if(requestCode == EDIT_COMMENT_REQUEST_CODE) { - if(resultCode == RESULT_OK) { - mAdapter.editComment(data.getStringExtra(EditCommentActivity.EXTRA_EDITED_COMMENT_CONTENT), - data.getExtras().getInt(EditCommentActivity.EXTRA_EDITED_COMMENT_POSITION)); - } - } - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - comments = mAdapter.getVisibleComments(); - Bridge.saveInstanceState(this, outState); - } - - @Override - public void onBackPressed() { - if(orientation == getResources().getConfiguration().orientation) { - super.onBackPressed(); - } else { - finish(); - } - } - - @Override - protected void onDestroy() { - EventBus.getDefault().unregister(this); - super.onDestroy(); - Bridge.clear(this); - } - - @Override - public void flairSelected(Flair flair) { - Map params = new HashMap<>(); - params.put(RedditUtils.API_TYPE_KEY, RedditUtils.API_TYPE_JSON); - params.put(RedditUtils.FLAIR_TEMPLATE_ID_KEY, flair.getId()); - params.put(RedditUtils.LINK_KEY, mPost.getFullName()); - params.put(RedditUtils.TEXT_KEY, flair.getText()); - - mOauthRetrofit.create(RedditAPI.class).selectFlair(mPost.getSubredditNamePrefixed(), - RedditUtils.getOAuthHeader(mAccessToken), params).enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if(response.isSuccessful()) { - refresh(true, false); - showMessage(R.string.update_flair_success); - } else { - showMessage(R.string.update_flair_failed); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - showMessage(R.string.update_flair_failed); - } - }); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java deleted file mode 100644 index 24a292a2..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java +++ /dev/null @@ -1,655 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.AsyncTask; -import android.os.Build; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProvider; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.bumptech.glide.request.RequestOptions; -import com.google.android.material.appbar.AppBarLayout; -import com.google.android.material.appbar.CollapsingToolbarLayout; -import com.google.android.material.chip.Chip; -import com.google.android.material.floatingactionbutton.FloatingActionButton; -import com.google.android.material.snackbar.Snackbar; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import javax.inject.Inject; -import javax.inject.Named; - -import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditDao; -import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditData; -import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditViewModel; -import butterknife.BindView; -import butterknife.ButterKnife; -import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import pl.droidsonroids.gif.GifImageView; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class ViewSubredditDetailActivity extends AppCompatActivity implements SortTypeBottomSheetFragment.SortTypeSelectionCallback, - PostTypeBottomSheetFragment.PostTypeSelectionCallback { - - static final String EXTRA_SUBREDDIT_NAME_KEY = "ESN"; - static final String EXTRA_MESSAGE_FULLNAME = "ENF"; - static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; - - private static final String FETCH_SUBREDDIT_INFO_STATE = "FSIS"; - private static final String CURRENT_ONLINE_SUBSCRIBERS_STATE = "COSS"; - private static final String FRAGMENT_OUT_STATE_KEY = "FOSK"; - private static final String IS_IN_LAZY_MODE_STATE = "IILMS"; - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - private static final String ACCOUNT_NAME_STATE = "ANS"; - private static final String MESSAGE_FULLNAME_STATE = "MFS"; - private static final String NEW_ACCOUNT_NAME_STATE = "NANS"; - - @BindView(R.id.coordinator_layout_view_subreddit_detail_activity) CoordinatorLayout coordinatorLayout; - @BindView(R.id.appbar_layout_view_subreddit_detail) AppBarLayout appBarLayout; - @BindView(R.id.collapsing_toolbar_layout_view_subreddit_detail_activity) CollapsingToolbarLayout collapsingToolbarLayout; - @BindView(R.id.toolbar) Toolbar toolbar; - @BindView(R.id.banner_image_view_view_subreddit_detail_activity) GifImageView bannerImageView; - @BindView(R.id.icon_gif_image_view_view_subreddit_detail_activity) GifImageView iconGifImageView; - @BindView(R.id.subscribe_subreddit_chip_view_subreddit_detail_activity) Chip subscribeSubredditChip; - @BindView(R.id.subreddit_name_text_view_view_subreddit_detail_activity) TextView subredditNameTextView; - @BindView(R.id.subscriber_count_text_view_view_subreddit_detail_activity) TextView nSubscribersTextView; - @BindView(R.id.online_subscriber_count_text_view_view_subreddit_detail_activity) TextView nOnlineSubscribersTextView; - @BindView(R.id.description_text_view_view_subreddit_detail_activity) TextView descriptionTextView; - @BindView(R.id.fab_view_subreddit_detail_activity) FloatingActionButton fab; - - private boolean mNullAccessToken = false; - private String mAccessToken; - private String mAccountName; - private String subredditName; - private boolean mFetchSubredditInfoSuccess = false; - private int mNCurrentOnlineSubscribers = 0; - private boolean subscriptionReady = false; - private boolean isInLazyMode = false; - private boolean showToast = false; - private String mMessageFullname; - private String mNewAccountName; - - private RequestManager glide; - private Fragment mFragment; - private Menu mMenu; - private AppBarLayout.LayoutParams params; - private PostTypeBottomSheetFragment postTypeBottomSheetFragment; - private SortTypeBottomSheetFragment sortTypeBottomSheetFragment; - - private SubredditViewModel mSubredditViewModel; - - @Inject - @Named("no_oauth") - Retrofit mRetrofit; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_view_subreddit_detail); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - Resources resources = getResources(); - - if(resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) { - Window window = getWindow(); - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - - boolean lightNavBar = false; - if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - lightNavBar = true; - } - boolean finalLightNavBar = lightNavBar; - - View decorView = window.getDecorView(); - appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { - @Override - void onStateChanged(AppBarLayout appBarLayout, State state) { - if (state == State.COLLAPSED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } else if (state == State.EXPANDED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - } - } - }); - - int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); - if (navBarResourceId > 0) { - CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) fab.getLayoutParams(); - params.bottomMargin = resources.getDimensionPixelSize(navBarResourceId); - fab.setLayoutParams(params); - - showToast = true; - } - } - } - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - subredditName = getIntent().getStringExtra(EXTRA_SUBREDDIT_NAME_KEY); - - if(savedInstanceState == null) { - mMessageFullname = getIntent().getStringExtra(EXTRA_MESSAGE_FULLNAME); - mNewAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); - getCurrentAccountAndBindView(); - } else { - mFetchSubredditInfoSuccess = savedInstanceState.getBoolean(FETCH_SUBREDDIT_INFO_STATE); - mNCurrentOnlineSubscribers = savedInstanceState.getInt(CURRENT_ONLINE_SUBSCRIBERS_STATE); - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); - isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); - mMessageFullname = savedInstanceState.getString(MESSAGE_FULLNAME_STATE); - mNewAccountName = savedInstanceState.getString(NEW_ACCOUNT_NAME_STATE); - - if(!mNullAccessToken && mAccessToken == null) { - getCurrentAccountAndBindView(); - } else { - bindView(false); - mFragment = getSupportFragmentManager().getFragment(savedInstanceState, FRAGMENT_OUT_STATE_KEY); - getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_view_subreddit_detail_activity, mFragment).commit(); - } - - if(mFetchSubredditInfoSuccess) { - nOnlineSubscribersTextView.setText(getString(R.string.online_subscribers_number_detail, mNCurrentOnlineSubscribers)); - } - } - - fetchSubredditData(); - - postTypeBottomSheetFragment = new PostTypeBottomSheetFragment(); - - sortTypeBottomSheetFragment = new SortTypeBottomSheetFragment(); - Bundle bottomSheetBundle = new Bundle(); - bottomSheetBundle.putBoolean(SortTypeBottomSheetFragment.EXTRA_NO_BEST_TYPE, true); - sortTypeBottomSheetFragment.setArguments(bottomSheetBundle); - - params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); - - //Get status bar height - int statusBarHeight = 0; - int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); - if (resourceId > 0) { - statusBarHeight = getResources().getDimensionPixelSize(resourceId); - } - - String title = "r/" + subredditName; - subredditNameTextView.setText(title); - - toolbar.setTitle(title); - ViewGroup.MarginLayoutParams toolbarParams = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); - toolbarParams.topMargin = statusBarHeight; - toolbar.setLayoutParams(toolbarParams); - setSupportActionBar(toolbar); - - glide = Glide.with(this); - - mSubredditViewModel = new ViewModelProvider(this, - new SubredditViewModel.Factory(getApplication(), mRedditDataRoomDatabase, subredditName)) - .get(SubredditViewModel.class); - mSubredditViewModel.getSubredditLiveData().observe(this, subredditData -> { - if(subredditData != null) { - if(subredditData.getBannerUrl().equals("")) { - iconGifImageView.setOnClickListener(view -> { - //Do nothing as it has no image - }); - } else { - glide.load(subredditData.getBannerUrl()).into(bannerImageView); - bannerImageView.setOnClickListener(view -> { - Intent intent = new Intent(ViewSubredditDetailActivity.this, ViewImageActivity.class); - intent.putExtra(ViewImageActivity.TITLE_KEY, title); - intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, subredditData.getBannerUrl()); - intent.putExtra(ViewImageActivity.FILE_NAME_KEY, subredditName + "-banner"); - startActivity(intent); - }); - } - - if(subredditData.getIconUrl().equals("")) { - glide.load(getDrawable(R.drawable.subreddit_default_icon)) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0))) - .into(iconGifImageView); - iconGifImageView.setOnClickListener(view -> { - //Do nothing as it is a default icon - }); - } else { - glide.load(subredditData.getIconUrl()) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0))) - .error(glide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0)))) - .into(iconGifImageView); - iconGifImageView.setOnClickListener(view -> { - Intent intent = new Intent(ViewSubredditDetailActivity.this, ViewImageActivity.class); - intent.putExtra(ViewImageActivity.TITLE_KEY, title); - intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, subredditData.getIconUrl()); - intent.putExtra(ViewImageActivity.FILE_NAME_KEY, subredditName + "-icon"); - startActivity(intent); - }); - } - - String subredditFullName = "r/" + subredditData.getName(); - if(!title.equals(subredditFullName)) { - getSupportActionBar().setTitle(subredditFullName); - } - subredditNameTextView.setText(subredditFullName); - String nSubscribers = getString(R.string.subscribers_number_detail, subredditData.getNSubscribers()); - nSubscribersTextView.setText(nSubscribers); - if(subredditData.getDescription().equals("")) { - descriptionTextView.setVisibility(View.GONE); - } else { - descriptionTextView.setVisibility(View.VISIBLE); - descriptionTextView.setText(subredditData.getDescription()); - } - } - }); - - fab.setOnClickListener(view -> { - if(mAccessToken == null) { - Toast.makeText(ViewSubredditDetailActivity.this, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - postTypeBottomSheetFragment.show(getSupportFragmentManager(), postTypeBottomSheetFragment.getTag()); - }); - } - - private void getCurrentAccountAndBindView() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(mNewAccountName != null) { - if(account == null || !account.getUsername().equals(mNewAccountName)) { - new SwitchAccountAsyncTask(mRedditDataRoomDatabase, mNewAccountName, newAccount -> { - EventBus.getDefault().post(new SwitchAccountEvent(getClass().getName())); - Toast.makeText(this, R.string.account_switched, Toast.LENGTH_SHORT).show(); - - mNewAccountName = null; - if(newAccount == null) { - mNullAccessToken = true; - } else { - mAccessToken = newAccount.getAccessToken(); - mAccountName = newAccount.getUsername(); - } - - bindView(true); - }).execute(); - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - bindView(true); - } - } else { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - } - - bindView(true); - } - }).execute(); - } - - private void fetchSubredditData() { - if(!mFetchSubredditInfoSuccess) { - FetchSubredditData.fetchSubredditData(mRetrofit, subredditName, new FetchSubredditData.FetchSubredditDataListener() { - @Override - public void onFetchSubredditDataSuccess(SubredditData subredditData, int nCurrentOnlineSubscribers) { - mNCurrentOnlineSubscribers = nCurrentOnlineSubscribers; - nOnlineSubscribersTextView.setText(getString(R.string.online_subscribers_number_detail, nCurrentOnlineSubscribers)); - new InsertSubredditDataAsyncTask(mRedditDataRoomDatabase, subredditData, () -> mFetchSubredditInfoSuccess = true).execute(); - } - - @Override - public void onFetchSubredditDataFail() { - makeSnackbar(R.string.cannot_fetch_subreddit_info, true); - mFetchSubredditInfoSuccess = false; - } - }); - } - } - - private void bindView(boolean initializeFragment) { - if(mAccessToken != null && mMessageFullname != null) { - ReadMessage.readMessage(mOauthRetrofit, mAccessToken, mMessageFullname, new ReadMessage.ReadMessageListener() { - @Override - public void readSuccess() { - mMessageFullname = null; - } - - @Override - public void readFailed() { - - } - }); - } - - subscribeSubredditChip.setOnClickListener(view -> { - if(mAccessToken == null) { - Toast.makeText(ViewSubredditDetailActivity.this, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - if(subscriptionReady) { - subscriptionReady = false; - if(subscribeSubredditChip.getText().equals(getResources().getString(R.string.subscribe))) { - SubredditSubscription.subscribeToSubreddit(mOauthRetrofit, mRetrofit, mAccessToken, - subredditName, mAccountName, mRedditDataRoomDatabase, - new SubredditSubscription.SubredditSubscriptionListener() { - @Override - public void onSubredditSubscriptionSuccess() { - subscribeSubredditChip.setText(R.string.unsubscribe); - subscribeSubredditChip.setChipBackgroundColor(getResources().getColorStateList(R.color.colorAccent)); - makeSnackbar(R.string.subscribed, false); - subscriptionReady = true; - } - - @Override - public void onSubredditSubscriptionFail() { - makeSnackbar(R.string.subscribe_failed, false); - subscriptionReady = true; - } - }); - } else { - SubredditSubscription.unsubscribeToSubreddit(mOauthRetrofit, mAccessToken, - subredditName, mAccountName, mRedditDataRoomDatabase, - new SubredditSubscription.SubredditSubscriptionListener() { - @Override - public void onSubredditSubscriptionSuccess() { - subscribeSubredditChip.setText(R.string.subscribe); - subscribeSubredditChip.setChipBackgroundColor(getResources().getColorStateList(R.color.backgroundColorPrimaryDark)); - makeSnackbar(R.string.unsubscribed, false); - subscriptionReady = true; - } - - @Override - public void onSubredditSubscriptionFail() { - makeSnackbar(R.string.unsubscribe_failed, false); - subscriptionReady = true; - } - }); - } - } - }); - - new CheckIsSubscribedToSubredditAsyncTask(mRedditDataRoomDatabase, subredditName, mAccountName, - new CheckIsSubscribedToSubredditAsyncTask.CheckIsSubscribedToSubredditListener() { - @Override - public void isSubscribed() { - subscribeSubredditChip.setText(R.string.unsubscribe); - subscribeSubredditChip.setChipBackgroundColor(getResources().getColorStateList(R.color.colorAccent)); - subscriptionReady = true; - } - - @Override - public void isNotSubscribed() { - subscribeSubredditChip.setText(R.string.subscribe); - subscribeSubredditChip.setChipBackgroundColor(getResources().getColorStateList(R.color.backgroundColorPrimaryDark)); - subscriptionReady = true; - } - }).execute(); - - if(initializeFragment) { - mFragment = new PostFragment(); - Bundle bundle = new Bundle(); - bundle.putString(PostFragment.EXTRA_NAME, subredditName); - bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_SUBREDDIT); - bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_BEST); - bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); - bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - mFragment.setArguments(bundle); - getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_view_subreddit_detail_activity, mFragment).commit(); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.view_subreddit_detail_activity, menu); - mMenu = menu; - MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_view_subreddit_detail_activity); - if(isInLazyMode) { - lazyModeItem.setTitle(R.string.action_stop_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED); - collapsingToolbarLayout.setLayoutParams(params); - } else { - lazyModeItem.setTitle(R.string.action_start_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | - AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED); - collapsingToolbarLayout.setLayoutParams(params); - } - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; - case R.id.action_sort_view_subreddit_detail_activity: - sortTypeBottomSheetFragment.show(getSupportFragmentManager(), sortTypeBottomSheetFragment.getTag()); - return true; - case R.id.action_search_view_subreddit_detail_activity: - Intent intent = new Intent(this, SearchActivity.class); - intent.putExtra(SearchActivity.EXTRA_SUBREDDIT_NAME, subredditName); - intent.putExtra(SearchActivity.EXTRA_SUBREDDIT_IS_USER, false); - intent.putExtra(SearchActivity.EXTRA_SEARCH_ONLY_SUBREDDITS, false); - startActivity(intent); - break; - case R.id.action_refresh_view_subreddit_detail_activity: - if(mMenu != null) { - mMenu.findItem(R.id.action_lazy_mode_view_subreddit_detail_activity).setTitle(R.string.action_start_lazy_mode); - } - if(mFragment instanceof FragmentCommunicator) { - ((FragmentCommunicator) mFragment).refresh(); - mFetchSubredditInfoSuccess = false; - fetchSubredditData(); - } - break; - case R.id.action_lazy_mode_view_subreddit_detail_activity: - MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_view_subreddit_detail_activity); - if(isInLazyMode) { - isInLazyMode = false; - ((FragmentCommunicator) mFragment).stopLazyMode(); - lazyModeItem.setTitle(R.string.action_start_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | - AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED); - collapsingToolbarLayout.setLayoutParams(params); - } else { - isInLazyMode = true; - if(((FragmentCommunicator) mFragment).startLazyMode()) { - lazyModeItem.setTitle(R.string.action_stop_lazy_mode); - appBarLayout.setExpanded(false); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED); - collapsingToolbarLayout.setLayoutParams(params); - } else { - isInLazyMode = false; - } - } - } - return false; - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean(FETCH_SUBREDDIT_INFO_STATE, mFetchSubredditInfoSuccess); - outState.putInt(CURRENT_ONLINE_SUBSCRIBERS_STATE, mNCurrentOnlineSubscribers); - outState.putBoolean(IS_IN_LAZY_MODE_STATE, isInLazyMode); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - outState.putString(ACCOUNT_NAME_STATE, mAccountName); - outState.putString(MESSAGE_FULLNAME_STATE, mMessageFullname); - outState.putString(NEW_ACCOUNT_NAME_STATE, mNewAccountName); - getSupportFragmentManager().putFragment(outState, FRAGMENT_OUT_STATE_KEY, mFragment); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - private void makeSnackbar(int resId, boolean retry) { - if(showToast) { - Toast.makeText(this, resId, Toast.LENGTH_SHORT).show(); - } else { - if(retry) { - Snackbar.make(coordinatorLayout, resId, Snackbar.LENGTH_SHORT).setAction(R.string.retry, - view -> fetchSubredditData()).show(); - } else { - Snackbar.make(coordinatorLayout, resId, Snackbar.LENGTH_SHORT).show(); - } - } - } - - @Override - public void sortTypeSelected(String sortType) { - ((PostFragment) mFragment).changeSortType(sortType); - } - - @Override - public void postTypeSelected(int postType) { - Intent intent; - switch (postType) { - case PostTypeBottomSheetFragment.TYPE_TEXT: - intent = new Intent(this, PostTextActivity.class); - intent.putExtra(PostTextActivity.EXTRA_SUBREDDIT_NAME, subredditName); - startActivity(intent); - break; - case PostTypeBottomSheetFragment.TYPE_LINK: - intent = new Intent(this, PostLinkActivity.class); - intent.putExtra(PostLinkActivity.EXTRA_SUBREDDIT_NAME, subredditName); - startActivity(intent); - break; - case PostTypeBottomSheetFragment.TYPE_IMAGE: - intent = new Intent(this, PostImageActivity.class); - intent.putExtra(PostImageActivity.EXTRA_SUBREDDIT_NAME, subredditName); - startActivity(intent); - break; - case PostTypeBottomSheetFragment.TYPE_VIDEO: - intent = new Intent(this, PostVideoActivity.class); - intent.putExtra(PostVideoActivity.EXTRA_SUBREDDIT_NAME, subredditName); - startActivity(intent); - } - } - - public void postScrollUp() { - fab.show(); - } - - public void postScrollDown() { - fab.hide(); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - if(!getClass().getName().equals(event.excludeActivityClassName)) { - finish(); - } - } - - @Subscribe - public void onChangeNSFWEvent(ChangeNSFWEvent changeNSFWEvent) { - ((FragmentCommunicator) mFragment).changeNSFW(changeNSFWEvent.nsfw); - } - - - private static class InsertSubredditDataAsyncTask extends AsyncTask { - - interface InsertSubredditDataAsyncTaskListener { - void insertSuccess(); - } - - private SubredditDao mSubredditDao; - private SubredditData subredditData; - private InsertSubredditDataAsyncTaskListener insertSubredditDataAsyncTaskListener; - - InsertSubredditDataAsyncTask(RedditDataRoomDatabase db, SubredditData subredditData, - InsertSubredditDataAsyncTaskListener insertSubredditDataAsyncTaskListener) { - mSubredditDao = db.subredditDao(); - this.subredditData = subredditData; - this.insertSubredditDataAsyncTaskListener = insertSubredditDataAsyncTaskListener; - } - - @Override - protected Void doInBackground(final Void... params) { - mSubredditDao.insert(subredditData); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - insertSubredditDataAsyncTaskListener.insertSuccess(); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java deleted file mode 100644 index 32657fd7..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java +++ /dev/null @@ -1,778 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.AsyncTask; -import android.os.Build; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentPagerAdapter; -import androidx.lifecycle.ViewModelProvider; -import androidx.viewpager.widget.ViewPager; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; -import com.bumptech.glide.request.RequestOptions; -import com.google.android.material.appbar.AppBarLayout; -import com.google.android.material.appbar.CollapsingToolbarLayout; -import com.google.android.material.chip.Chip; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import com.google.android.material.snackbar.Snackbar; -import com.google.android.material.tabs.TabLayout; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import javax.inject.Inject; -import javax.inject.Named; - -import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUserDao; -import ml.docilealligator.infinityforreddit.User.UserDao; -import ml.docilealligator.infinityforreddit.User.UserData; -import ml.docilealligator.infinityforreddit.User.UserViewModel; -import butterknife.BindView; -import butterknife.ButterKnife; -import jp.wasabeef.glide.transformations.RoundedCornersTransformation; -import pl.droidsonroids.gif.GifImageView; -import retrofit2.Retrofit; - -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; -import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; - -public class ViewUserDetailActivity extends AppCompatActivity implements UserThingSortTypeBottomSheetFragment.UserThingSortTypeSelectionCallback { - - static final String EXTRA_USER_NAME_KEY = "EUNK"; - static final String EXTRA_MESSAGE_FULLNAME = "ENF"; - static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; - - private static final String FETCH_USER_INFO_STATE = "FSIS"; - private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; - private static final String ACCESS_TOKEN_STATE = "ATS"; - private static final String ACCOUNT_NAME_STATE = "ANS"; - private static final String IS_IN_LAZY_MODE_STATE = "IILMS"; - private static final String MESSAGE_FULLNAME_STATE = "MFS"; - private static final String NEW_ACCOUNT_NAME_STATE = "NANS"; - - @BindView(R.id.coordinator_layout_view_user_detail_activity) CoordinatorLayout coordinatorLayout; - @BindView(R.id.view_pager_view_user_detail_activity) ViewPager viewPager; - @BindView(R.id.appbar_layout_view_user_detail) AppBarLayout appBarLayout; - @BindView(R.id.tab_layout_view_user_detail_activity) TabLayout tabLayout; - @BindView(R.id.collapsing_toolbar_layout_view_user_detail_activity) CollapsingToolbarLayout collapsingToolbarLayout; - @BindView(R.id.banner_image_view_view_user_detail_activity) GifImageView bannerImageView; - @BindView(R.id.icon_gif_image_view_view_user_detail_activity) GifImageView iconGifImageView; - @BindView(R.id.user_name_text_view_view_user_detail_activity) TextView userNameTextView; - @BindView(R.id.subscribe_user_chip_view_user_detail_activity) Chip subscribeUserChip; - @BindView(R.id.karma_text_view_view_user_detail_activity) TextView karmaTextView; - - private SectionsPagerAdapter sectionsPagerAdapter; - - private SubscribedUserDao subscribedUserDao; - private RequestManager glide; - private UserViewModel userViewModel; - private Menu mMenu; - private AppBarLayout.LayoutParams params; - - private UserThingSortTypeBottomSheetFragment userThingSortTypeBottomSheetFragment; - - private boolean mNullAccessToken = false; - private String mAccessToken; - private String mAccountName; - private String username; - private boolean subscriptionReady = false; - private boolean mFetchUserInfoSuccess = false; - private boolean isInLazyMode = false; - private int expandedTabTextColor; - private int expandedTabBackgroundColor; - private int expandedTabIndicatorColor; - private int collapsedTabTextColor; - private int collapsedTabBackgroundColor; - private int collapsedTabIndicatorColor; - private boolean showToast = false; - private String mMessageFullname; - private String mNewAccountName; - - @Inject - @Named("no_oauth") - Retrofit mRetrofit; - - @Inject - @Named("oauth") - Retrofit mOauthRetrofit; - - @Inject - RedditDataRoomDatabase mRedditDataRoomDatabase; - - @Inject - SharedPreferences mSharedPreferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ((Infinity) getApplication()).getAppComponent().inject(this); - - getTheme().applyStyle(FontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.FONT_SIZE_KEY, FontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(TitleFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.TITLE_FONT_SIZE_KEY, TitleFontStyle.Normal.name())).getResId(), true); - - getTheme().applyStyle(ContentFontStyle.valueOf(mSharedPreferences - .getString(SharedPreferencesUtils.CONTENT_FONT_SIZE_KEY, ContentFontStyle.Normal.name())).getResId(), true); - - setContentView(R.layout.activity_view_user_detail); - - ButterKnife.bind(this); - - EventBus.getDefault().register(this); - - boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; - int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); - switch (themeType) { - case 0: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); - break; - case 1: - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); - break; - case 2: - if(systemDefault) { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); - } else { - AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); - } - - } - - username = getIntent().getStringExtra(EXTRA_USER_NAME_KEY); - - if (savedInstanceState == null) { - mMessageFullname = getIntent().getStringExtra(EXTRA_MESSAGE_FULLNAME); - mNewAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); - getCurrentAccountAndInitializeViewPager(); - } else { - mFetchUserInfoSuccess = savedInstanceState.getBoolean(FETCH_USER_INFO_STATE); - mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); - mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); - mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); - isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); - mMessageFullname = savedInstanceState.getString(MESSAGE_FULLNAME_STATE); - mNewAccountName = savedInstanceState.getString(NEW_ACCOUNT_NAME_STATE); - - if (!mNullAccessToken && mAccessToken == null) { - getCurrentAccountAndInitializeViewPager(); - } else { - initializeViewPager(); - } - } - - fetchUserInfo(); - - params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); - - Resources resources = getResources(); - - //Get status bar height - int statusBarHeight = 0; - int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android"); - if (resourceId > 0) { - statusBarHeight = resources.getDimensionPixelSize(resourceId); - } - - Toolbar toolbar = findViewById(R.id.toolbar); - ViewGroup.MarginLayoutParams toolbarLayoutParams = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); - toolbarLayoutParams.topMargin = statusBarHeight; - toolbar.setLayoutParams(toolbarLayoutParams); - - String title = "u/" + username; - userNameTextView.setText(title); - toolbar.setTitle(title); - - setSupportActionBar(toolbar); - - expandedTabTextColor = resources.getColor(R.color.tabLayoutWithExpandedCollapsingToolbarTextColor); - expandedTabBackgroundColor = resources.getColor(R.color.tabLayoutWithExpandedCollapsingToolbarTabBackground); - expandedTabIndicatorColor = resources.getColor(R.color.tabLayoutWithExpandedCollapsingToolbarTabIndicator); - - collapsedTabTextColor = resources.getColor(R.color.tabLayoutWithCollapsedCollapsingToolbarTextColor); - collapsedTabBackgroundColor = resources.getColor(R.color.tabLayoutWithCollapsedCollapsingToolbarTabBackground); - collapsedTabIndicatorColor = resources.getColor(R.color.tabLayoutWithCollapsedCollapsingToolbarTabIndicator); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 - && (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT - || resources.getBoolean(R.bool.isTablet))) { - Window window = getWindow(); - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - - boolean lightNavBar = false; - if((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - lightNavBar = true; - } - boolean finalLightNavBar = lightNavBar; - - View decorView = window.getDecorView(); - appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { - @Override - void onStateChanged(AppBarLayout appBarLayout, State state) { - if (state == State.COLLAPSED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - tabLayout.setTabTextColors(collapsedTabTextColor, collapsedTabTextColor); - tabLayout.setSelectedTabIndicatorColor(collapsedTabIndicatorColor); - tabLayout.setBackgroundColor(collapsedTabBackgroundColor); - } else if (state == State.EXPANDED) { - if(finalLightNavBar) { - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - tabLayout.setTabTextColors(expandedTabTextColor, expandedTabTextColor); - tabLayout.setSelectedTabIndicatorColor(expandedTabIndicatorColor); - tabLayout.setBackgroundColor(expandedTabBackgroundColor); - } - } - }); - - showToast = true; - } else { - appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { - @Override - void onStateChanged(AppBarLayout appBarLayout, State state) { - if (state == State.EXPANDED) { - tabLayout.setTabTextColors(expandedTabTextColor, expandedTabTextColor); - tabLayout.setSelectedTabIndicatorColor(expandedTabIndicatorColor); - tabLayout.setBackgroundColor(expandedTabBackgroundColor); - } else if (state == State.COLLAPSED) { - tabLayout.setTabTextColors(collapsedTabTextColor, collapsedTabTextColor); - tabLayout.setSelectedTabIndicatorColor(collapsedTabIndicatorColor); - tabLayout.setBackgroundColor(collapsedTabBackgroundColor); - } - } - }); - } - - subscribedUserDao = mRedditDataRoomDatabase.subscribedUserDao(); - glide = Glide.with(this); - - userViewModel = new ViewModelProvider(this, new UserViewModel.Factory(getApplication(), mRedditDataRoomDatabase, username)) - .get(UserViewModel.class); - userViewModel.getUserLiveData().observe(this, userData -> { - if (userData != null) { - if (userData.getBanner().equals("")) { - bannerImageView.setOnClickListener(view -> { - //Do nothing since the user has no banner image - }); - } else { - glide.load(userData.getBanner()).into(bannerImageView); - bannerImageView.setOnClickListener(view -> { - Intent intent = new Intent(this, ViewImageActivity.class); - intent.putExtra(ViewImageActivity.TITLE_KEY, title); - intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, userData.getBanner()); - intent.putExtra(ViewImageActivity.FILE_NAME_KEY, username + "-banner"); - startActivity(intent); - }); - } - - if (userData.getIconUrl().equals("")) { - glide.load(getDrawable(R.drawable.subreddit_default_icon)) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0))) - .into(iconGifImageView); - iconGifImageView.setOnClickListener(view -> { - //Do nothing since the user has no icon image - }); - } else { - glide.load(userData.getIconUrl()) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0))) - .error(glide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0)))) - .into(iconGifImageView); - - iconGifImageView.setOnClickListener(view -> { - Intent intent = new Intent(this, ViewImageActivity.class); - intent.putExtra(ViewImageActivity.TITLE_KEY, title); - intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, userData.getIconUrl()); - intent.putExtra(ViewImageActivity.FILE_NAME_KEY, username + "-icon"); - startActivity(intent); - }); - } - - if (userData.isCanBeFollowed()) { - subscribeUserChip.setVisibility(View.VISIBLE); - subscribeUserChip.setOnClickListener(view -> { - if(mAccessToken == null) { - Toast.makeText(ViewUserDetailActivity.this, R.string.login_first, Toast.LENGTH_SHORT).show(); - return; - } - - if (subscriptionReady) { - subscriptionReady = false; - if (subscribeUserChip.getText().equals(resources.getString(R.string.follow))) { - UserFollowing.followUser(mOauthRetrofit, mRetrofit, mAccessToken, - username, mAccountName, subscribedUserDao, new UserFollowing.UserFollowingListener() { - @Override - public void onUserFollowingSuccess() { - subscribeUserChip.setText(R.string.unfollow); - subscribeUserChip.setChipBackgroundColor(resources.getColorStateList(R.color.colorAccent)); - showMessage(R.string.followed, false); - subscriptionReady = true; - } - - @Override - public void onUserFollowingFail() { - showMessage(R.string.follow_failed, false); - subscriptionReady = true; - } - }); - } else { - UserFollowing.unfollowUser(mOauthRetrofit, mRetrofit, mAccessToken, - username, mAccountName, subscribedUserDao, new UserFollowing.UserFollowingListener() { - @Override - public void onUserFollowingSuccess() { - subscribeUserChip.setText(R.string.follow); - subscribeUserChip.setChipBackgroundColor(resources.getColorStateList(R.color.backgroundColorPrimaryDark)); - showMessage(R.string.unfollowed, false); - subscriptionReady = true; - } - - @Override - public void onUserFollowingFail() { - showMessage(R.string.unfollow_failed, false); - subscriptionReady = true; - } - }); - } - } - }); - - new CheckIsFollowingUserAsyncTask(subscribedUserDao, username, mAccountName, new CheckIsFollowingUserAsyncTask.CheckIsFollowingUserListener() { - @Override - public void isSubscribed() { - subscribeUserChip.setText(R.string.unfollow); - subscribeUserChip.setChipBackgroundColor(resources.getColorStateList(R.color.colorAccent)); - subscriptionReady = true; - } - - @Override - public void isNotSubscribed() { - subscribeUserChip.setText(R.string.follow); - subscribeUserChip.setChipBackgroundColor(resources.getColorStateList(R.color.backgroundColorPrimaryDark)); - subscriptionReady = true; - } - }).execute(); - } else { - subscribeUserChip.setVisibility(View.GONE); - } - - String userFullName = "u/" + userData.getName(); - userNameTextView.setText(userFullName); - if (!title.equals(userFullName)) { - getSupportActionBar().setTitle(userFullName); - } - String karma = getString(R.string.karma_info, userData.getKarma()); - karmaTextView.setText(karma); - } - }); - - userThingSortTypeBottomSheetFragment = new UserThingSortTypeBottomSheetFragment(); - } - - private void getCurrentAccountAndInitializeViewPager() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(mNewAccountName != null) { - if(account == null || !account.getUsername().equals(mNewAccountName)) { - new SwitchAccountAsyncTask(mRedditDataRoomDatabase, mNewAccountName, newAccount -> { - EventBus.getDefault().post(new SwitchAccountEvent(getClass().getName())); - Toast.makeText(this, R.string.account_switched, Toast.LENGTH_SHORT).show(); - - mNewAccountName = null; - if(newAccount == null) { - mNullAccessToken = true; - } else { - mAccessToken = newAccount.getAccessToken(); - mAccountName = newAccount.getUsername(); - } - - initializeViewPager(); - }).execute(); - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - initializeViewPager(); - } - } else { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - } - - initializeViewPager(); - } - }).execute(); - } - - private void initializeViewPager() { - sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); - viewPager.setAdapter(sectionsPagerAdapter); - viewPager.setOffscreenPageLimit(2); - tabLayout.setupWithViewPager(viewPager); - - viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - - } - - @Override - public void onPageSelected(int position) { - if(isInLazyMode) { - if(viewPager.getCurrentItem() == 0) { - sectionsPagerAdapter.resumeLazyMode(); - } else { - sectionsPagerAdapter.pauseLazyMode(); - } - } - } - - @Override - public void onPageScrollStateChanged(int state) { - - } - }); - - if(mAccessToken != null && mMessageFullname != null) { - ReadMessage.readMessage(mOauthRetrofit, mAccessToken, mMessageFullname, new ReadMessage.ReadMessageListener() { - @Override - public void readSuccess() { - mMessageFullname = null; - } - - @Override - public void readFailed() { - - } - }); - } - } - - private void fetchUserInfo() { - if (!mFetchUserInfoSuccess) { - FetchUserData.fetchUserData(mRetrofit, username, new FetchUserData.FetchUserDataListener() { - @Override - public void onFetchUserDataSuccess(UserData userData) { - new InsertUserDataAsyncTask(mRedditDataRoomDatabase.userDao(), userData, - () -> mFetchUserInfoSuccess = true).execute(); - } - - @Override - public void onFetchUserDataFailed() { - showMessage(R.string.cannot_fetch_user_info, true); - mFetchUserInfoSuccess = false; - } - }); - } - } - - void deleteComment(String fullName) { - new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme) - .setTitle(R.string.delete_this_comment) - .setMessage(R.string.are_you_sure) - .setPositiveButton(R.string.delete, (dialogInterface, i) - -> DeleteThing.delete(mOauthRetrofit, fullName, mAccessToken, new DeleteThing.DeleteThingListener() { - @Override - public void deleteSuccess() { - Toast.makeText(ViewUserDetailActivity.this, R.string.delete_post_success, Toast.LENGTH_SHORT).show(); - } - - @Override - public void deleteFailed() { - Toast.makeText(ViewUserDetailActivity.this, R.string.delete_post_failed, Toast.LENGTH_SHORT).show(); - } - })) - .setNegativeButton(R.string.cancel, null) - .show(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.view_user_detail_activity, menu); - mMenu = menu; - MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_view_user_detail_activity); - if (isInLazyMode) { - lazyModeItem.setTitle(R.string.action_stop_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED); - collapsingToolbarLayout.setLayoutParams(params); - } else { - lazyModeItem.setTitle(R.string.action_start_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | - AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED); - collapsingToolbarLayout.setLayoutParams(params); - } - - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; - case R.id.action_sort_view_user_detail_activity: - userThingSortTypeBottomSheetFragment.show(getSupportFragmentManager(), userThingSortTypeBottomSheetFragment.getTag()); - return true; - case R.id.action_search_view_user_detail_activity: - Intent intent = new Intent(this, SearchActivity.class); - intent.putExtra(SearchActivity.EXTRA_SUBREDDIT_NAME, username); - intent.putExtra(SearchActivity.EXTRA_SUBREDDIT_IS_USER, true); - intent.putExtra(SearchActivity.EXTRA_SEARCH_ONLY_SUBREDDITS, false); - startActivity(intent); - return true; - case R.id.action_refresh_view_user_detail_activity: - if(mMenu != null) { - mMenu.findItem(R.id.action_lazy_mode_view_user_detail_activity).setTitle(R.string.action_start_lazy_mode); - } - sectionsPagerAdapter.refresh(); - mFetchUserInfoSuccess = false; - fetchUserInfo(); - return true; - case R.id.action_lazy_mode_view_user_detail_activity: - MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_view_user_detail_activity); - if(isInLazyMode) { - isInLazyMode = false; - sectionsPagerAdapter.stopLazyMode(); - lazyModeItem.setTitle(R.string.action_start_lazy_mode); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | - AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED); - collapsingToolbarLayout.setLayoutParams(params); - } else { - isInLazyMode = true; - if(sectionsPagerAdapter.startLazyMode()) { - lazyModeItem.setTitle(R.string.action_stop_lazy_mode); - appBarLayout.setExpanded(false); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED); - collapsingToolbarLayout.setLayoutParams(params); - } else { - isInLazyMode = false; - } - } - return true; - } - return false; - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean(FETCH_USER_INFO_STATE, mFetchUserInfoSuccess); - outState.putBoolean(IS_IN_LAZY_MODE_STATE, isInLazyMode); - outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); - outState.putString(ACCESS_TOKEN_STATE, mAccessToken); - outState.putString(ACCOUNT_NAME_STATE, mAccountName); - outState.putString(MESSAGE_FULLNAME_STATE, mMessageFullname); - outState.putString(NEW_ACCOUNT_NAME_STATE, mNewAccountName); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - EventBus.getDefault().unregister(this); - } - - private void showMessage(int resId, boolean retry) { - if(showToast) { - Toast.makeText(this, resId, Toast.LENGTH_SHORT).show(); - } else { - if (retry) { - Snackbar.make(coordinatorLayout, resId, Snackbar.LENGTH_SHORT).setAction(R.string.retry, - view -> fetchUserInfo()).show(); - } else { - Snackbar.make(coordinatorLayout, resId, Snackbar.LENGTH_SHORT).show(); - } - } - } - - @Override - public void userThingSortTypeSelected(String sortType) { - sectionsPagerAdapter.changeSortType(sortType); - } - - @Subscribe - public void onAccountSwitchEvent(SwitchAccountEvent event) { - if(!getClass().getName().equals(event.excludeActivityClassName)) { - finish(); - } - } - - @Subscribe - public void onChangeNSFWEvent(ChangeNSFWEvent changeNSFWEvent) { - sectionsPagerAdapter.changeNSFW(changeNSFWEvent.nsfw); - } - - private static class InsertUserDataAsyncTask extends AsyncTask { - - interface InsertUserDataAsyncTaskListener { - void insertSuccess(); - } - - private UserDao userDao; - private UserData subredditData; - private InsertUserDataAsyncTaskListener insertUserDataAsyncTaskListener; - - InsertUserDataAsyncTask(UserDao userDao, UserData userData, - InsertUserDataAsyncTaskListener insertUserDataAsyncTaskListener) { - this.userDao = userDao; - this.subredditData = userData; - this.insertUserDataAsyncTaskListener = insertUserDataAsyncTaskListener; - } - - @Override - protected Void doInBackground(final Void... params) { - userDao.insert(subredditData); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - insertUserDataAsyncTaskListener.insertSuccess(); - } - } - - private class SectionsPagerAdapter extends FragmentPagerAdapter { - private PostFragment postFragment; - private CommentsListingFragment commentsListingFragment; - - SectionsPagerAdapter(FragmentManager fm) { - super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); - } - - @NonNull - @Override - public Fragment getItem(int position) { - if (position == 0) { - PostFragment fragment = new PostFragment(); - Bundle bundle = new Bundle(); - bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_USER); - bundle.putString(PostFragment.EXTRA_USER_NAME, username); - bundle.putString(PostFragment.EXTRA_USER_WHERE, PostDataSource.USER_WHERE_SUBMITTED); - bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_NEW); - bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); - bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - fragment.setArguments(bundle); - return fragment; - } - CommentsListingFragment fragment = new CommentsListingFragment(); - Bundle bundle = new Bundle(); - bundle.putString(CommentsListingFragment.EXTRA_USERNAME, username); - bundle.putString(CommentsListingFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - bundle.putString(CommentsListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); - bundle.putBoolean(CommentsListingFragment.EXTRA_ARE_SAVED_COMMENTS, false); - fragment.setArguments(bundle); - return fragment; - } - - @Override - public int getCount() { - return 2; - } - - @Override - public CharSequence getPageTitle(int position) { - switch (position) { - case 0: - return "Posts"; - case 1: - return "Comments"; - } - return null; - } - - @NonNull - @Override - public Object instantiateItem(@NonNull ViewGroup container, int position) { - Fragment fragment = (Fragment) super.instantiateItem(container, position); - switch (position) { - case 0: - postFragment = (PostFragment) fragment; - break; - case 1: - commentsListingFragment = (CommentsListingFragment) fragment; - } - return fragment; - } - - public void refresh() { - if (viewPager.getCurrentItem() == 0) { - if(postFragment != null) { - postFragment.refresh(); - } - } else { - if(commentsListingFragment != null) { - commentsListingFragment.refresh(); - } - } - } - - boolean startLazyMode() { - if(postFragment != null) { - return ((FragmentCommunicator) postFragment).startLazyMode(); - } - return false; - } - - void stopLazyMode() { - if(postFragment != null) { - ((FragmentCommunicator) postFragment).stopLazyMode(); - } - } - - void resumeLazyMode() { - if(postFragment != null) { - ((FragmentCommunicator) postFragment).resumeLazyMode(false); - } - } - - void pauseLazyMode() { - if(postFragment != null) { - ((FragmentCommunicator) postFragment).pauseLazyMode(false); - } - } - - public void changeSortType(String sortType) { - if(viewPager.getCurrentItem() == 0) { - if(postFragment != null) { - postFragment.changeSortType(sortType); - } - } else { - if(commentsListingFragment != null) { - commentsListingFragment.changeSortType(sortType); - } - } - } - - public void changeNSFW(boolean nsfw) { - if(postFragment != null) { - postFragment.changeNSFW(nsfw); - } - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewVideoActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewVideoActivity.java deleted file mode 100644 index 0dbac0b4..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewVideoActivity.java +++ /dev/null @@ -1,368 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.Manifest; -import android.animation.Animator; -import android.animation.ArgbEvaluator; -import android.animation.ValueAnimator; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.res.Configuration; -import android.graphics.PorterDuff; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.media.AudioManager; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.RelativeLayout; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatActivity; -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; - -import com.github.pwittchen.swipe.library.rx2.SimpleSwipeListener; -import com.github.pwittchen.swipe.library.rx2.Swipe; -import com.google.android.exoplayer2.ExoPlayerFactory; -import com.google.android.exoplayer2.Player; -import com.google.android.exoplayer2.SimpleExoPlayer; -import com.google.android.exoplayer2.source.hls.HlsMediaSource; -import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; -import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; -import com.google.android.exoplayer2.trackselection.TrackSelection; -import com.google.android.exoplayer2.trackselection.TrackSelector; -import com.google.android.exoplayer2.ui.PlayerView; -import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory; -import com.google.android.exoplayer2.util.Util; - -import butterknife.BindView; -import butterknife.ButterKnife; - -public class ViewVideoActivity extends AppCompatActivity { - - private static final int PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 0; - - static final String TITLE_KEY = "TK"; - static final String SUBREDDIT_KEY = "SK"; - static final String ID_KEY = "IK"; - - @BindView(R.id.relative_layout_view_video_activity) RelativeLayout relativeLayout; - @BindView(R.id.player_view_view_video_activity) PlayerView videoPlayerView; - - private Uri mVideoUri; - private SimpleExoPlayer player; - private DataSource.Factory dataSourceFactory; - - private Menu mMenu; - private Swipe swipe; - - private boolean wasPlaying; - private boolean isDownloading = false; - private float totalLengthY = 0.0f; - private float touchY = -1.0f; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_view_video); - ButterKnife.bind(this); - setVolumeControlStream(AudioManager.STREAM_MUSIC); - - ActionBar actionBar = getSupportActionBar(); - Drawable upArrow = getResources().getDrawable(R.drawable.ic_arrow_back_white_24dp); - actionBar.setHomeAsUpIndicator(upArrow); - actionBar.setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.transparentActionBarAndExoPlayerControllerColor))); - setTitle(""); - - if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || getResources().getBoolean(R.bool.isTablet)) { - //Set player controller bottom margin in order to display it above the navbar - int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android"); - LinearLayout controllerLinearLayout = findViewById(R.id.linear_layout_exo_playback_control_view); - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) controllerLinearLayout.getLayoutParams(); - params.bottomMargin = getResources().getDimensionPixelSize(resourceId); - } else { - //Set player controller right margin in order to display it above the navbar - int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android"); - LinearLayout controllerLinearLayout = findViewById(R.id.linear_layout_exo_playback_control_view); - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) controllerLinearLayout.getLayoutParams(); - params.rightMargin = getResources().getDimensionPixelSize(resourceId); - } - - Intent intent = getIntent(); - mVideoUri = intent.getData(); - - final float pxHeight = getResources().getDisplayMetrics().heightPixels; - - int activityColorFrom = getResources().getColor(android.R.color.black); - int actionBarColorFrom = getResources().getColor(R.color.transparentActionBarAndExoPlayerControllerColor); - int actionBarElementColorFrom = getResources().getColor(android.R.color.white); - int colorTo = getResources().getColor(android.R.color.transparent); - - final ValueAnimator activityColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), activityColorFrom, colorTo); - final ValueAnimator actionBarColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), actionBarColorFrom, colorTo); - final ValueAnimator actionBarElementColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), actionBarElementColorFrom, colorTo); - - activityColorAnimation.setDuration(300); // milliseconds - actionBarColorAnimation.setDuration(300); - actionBarElementColorAnimation.setDuration(300); - - activityColorAnimation.addUpdateListener(valueAnimator -> relativeLayout.setBackgroundColor((int) valueAnimator.getAnimatedValue())); - - actionBarColorAnimation.addUpdateListener(valueAnimator -> actionBar.setBackgroundDrawable(new ColorDrawable((int) valueAnimator.getAnimatedValue()))); - - actionBarElementColorAnimation.addUpdateListener(valueAnimator -> { - upArrow.setColorFilter((int) valueAnimator.getAnimatedValue(), PorterDuff.Mode.SRC_IN); - if(mMenu != null) { - Drawable drawable = mMenu.getItem(0).getIcon(); - drawable.setColorFilter((int) valueAnimator.getAnimatedValue(), PorterDuff.Mode.SRC_IN); - } - }); - - swipe = new Swipe(); - swipe.setListener(new SimpleSwipeListener() { - @Override - public void onSwipingUp(final MotionEvent event) { - float nowY = event.getY(); - float offset; - if(touchY == -1.0f) { - offset = 0.0f; - } else { - offset = nowY - touchY; - } - totalLengthY += offset; - touchY = nowY; - videoPlayerView.animate() - .y(totalLengthY) - .setDuration(0) - .start(); - } - - @Override - public boolean onSwipedUp(final MotionEvent event) { - videoPlayerView.animate() - .y(0) - .setDuration(300) - .start(); - - if(totalLengthY < -pxHeight / 8) { - videoPlayerView.animate() - .y(-pxHeight) - .setDuration(300) - .setListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animator) { - activityColorAnimation.start(); - actionBarColorAnimation.start(); - actionBarElementColorAnimation.start(); - } - - @Override - public void onAnimationEnd(Animator animator) { - finish(); - } - - @Override - public void onAnimationCancel(Animator animator) {} - - @Override - public void onAnimationRepeat(Animator animator) {} - }) - .start(); - } else { - videoPlayerView.animate() - .y(0) - .setDuration(300) - .start(); - } - - totalLengthY = 0.0f; - touchY = -1.0f; - return false; - } - - @Override - public void onSwipingDown(final MotionEvent event) { - float nowY = event.getY(); - float offset; - if(touchY == -1.0f) { - offset = 0.0f; - } else { - offset = nowY - touchY; - } - totalLengthY += offset; - touchY = nowY; - videoPlayerView.animate() - .y(totalLengthY) - .setDuration(0) - .start(); - } - - @Override - public boolean onSwipedDown(final MotionEvent event) { - if(totalLengthY > pxHeight / 8) { - videoPlayerView.animate() - .y(pxHeight) - .setDuration(300) - .setListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animator) { - activityColorAnimation.start(); - actionBarColorAnimation.start(); - actionBarElementColorAnimation.start(); - } - - @Override - public void onAnimationEnd(Animator animator) { - finish(); - } - - @Override - public void onAnimationCancel(Animator animator) {} - - @Override - public void onAnimationRepeat(Animator animator) {} - }) - .start(); - } else { - videoPlayerView.animate() - .y(0) - .setDuration(300) - .start(); - } - - totalLengthY = 0.0f; - touchY = -1.0f; - - return false; - } - }); - - videoPlayerView.setControllerVisibilityListener(visibility -> { - switch (visibility) { - case View.GONE: - getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_FULLSCREEN - | View.SYSTEM_UI_FLAG_IMMERSIVE); - break; - case View.VISIBLE: - getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); - } - }); - - TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(); - TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); - player = ExoPlayerFactory.newSimpleInstance(this, trackSelector); - videoPlayerView.setPlayer(player); - // Produces DataSource instances through which media data is loaded. - dataSourceFactory = new DefaultHttpDataSourceFactory(Util.getUserAgent(this, "Infinity")); - // Prepare the player with the source. - player.prepare(new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(mVideoUri)); - - player.setRepeatMode(Player.REPEAT_MODE_ALL); - player.setPlayWhenReady(true); - wasPlaying = true; - } - - /*@Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.view_video, menu); - mMenu = menu; - return true; - }*/ - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - swipe.dispatchTouchEvent(ev); - return super.dispatchTouchEvent(ev); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - player.release(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; - case R.id.action_download_view_video: - isDownloading = true; - if (Build.VERSION.SDK_INT >= 23) { - if (ContextCompat.checkSelfPermission(this, - Manifest.permission.WRITE_EXTERNAL_STORAGE) - != PackageManager.PERMISSION_GRANTED) { - - // Permission is not granted - // No explanation needed; request the permission - ActivityCompat.requestPermissions(this, - new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE); - } else { - // Permission has already been granted - download(); - } - } else { - download(); - } - return true; - } - - return false; - } - - @Override - protected void onStart() { - super.onStart(); - if(wasPlaying) { - player.setPlayWhenReady(true); - } - } - - @Override - protected void onStop() { - super.onStop(); - wasPlaying = player.getPlayWhenReady(); - player.setPlayWhenReady(false); - } - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - if(requestCode == PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE && grantResults.length > 0) { - if(grantResults[0] == PackageManager.PERMISSION_DENIED) { - Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show(); - } else if(grantResults[0] == PackageManager.PERMISSION_GRANTED && isDownloading) { - download(); - } - isDownloading = false; - } - } - - private void download() { - isDownloading = false; - } - - @Override - protected void onPause() { - super.onPause(); - overridePendingTransition(0, 0); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/VoteThing.java b/app/src/main/java/ml/docilealligator/infinityforreddit/VoteThing.java index 8c2d2f01..af71794a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/VoteThing.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/VoteThing.java @@ -1,7 +1,5 @@ package ml.docilealligator.infinityforreddit; -import android.util.Log; - import androidx.annotation.NonNull; import java.util.HashMap; @@ -15,21 +13,21 @@ import retrofit2.Retrofit; * Created by alex on 3/14/18. */ -class VoteThing { +public class VoteThing { - interface VoteThingListener { + public interface VoteThingListener { void onVoteThingSuccess(int position); void onVoteThingFail(int position); } - interface VoteThingWithoutPositionListener { + public interface VoteThingWithoutPositionListener { void onVoteThingSuccess(); void onVoteThingFail(); } - static void voteThing(final Retrofit retrofit, String accessToken, - final VoteThingListener voteThingListener, final String fullName, - final String point, final int position) { + public static void voteThing(final Retrofit retrofit, String accessToken, + final VoteThingListener voteThingListener, final String fullName, + final String point, final int position) { RedditAPI api = retrofit.create(RedditAPI.class); Map params = new HashMap<>(); @@ -55,7 +53,7 @@ class VoteThing { }); } - static void voteThing(final Retrofit retrofit, String accessToken, + public static void voteThing(final Retrofit retrofit, String accessToken, final VoteThingWithoutPositionListener voteThingWithoutPositionListener, final String fullName, final String point) { RedditAPI api = retrofit.create(RedditAPI.class); diff --git a/app/src/main/res/layout/activity_account_posts.xml b/app/src/main/res/layout/activity_account_posts.xml index bc2af273..cabb67f2 100644 --- a/app/src/main/res/layout/activity_account_posts.xml +++ b/app/src/main/res/layout/activity_account_posts.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".AccountPostsActivity"> + tools:context=".Activity.AccountPostsActivity"> + tools:context=".Activity.AccountPostsActivity"> + tools:context=".Activity.EditCommentActivity"> + tools:context=".Activity.EditPostActivity"> + tools:application="ml.docilealligator.infinityforreddit.Activity.LoginActivity"> + tools:application="ml.docilealligator.infinityforreddit.Activity.ViewImageActivity"> + tools:context=".Activity.ViewMessageActivity"> + tools:application="ml.docilealligator.infinityforreddit.Activity.ViewVideoActivity"> + tools:application="ml.docilealligator.infinityforreddit.Activity.MainActivity"> + tools:application="ml.docilealligator.infinityforreddit.Fragment.CommentsListingFragment"> + tools:context=".Fragment.ModifyCommentBottomSheetFragment"> + tools:application="ml.docilealligator.infinityforreddit.Fragment.PostFragment"> + tools:application="ml.docilealligator.infinityforreddit.Activity.AccountSavedThingActivity"> + tools:application="ml.docilealligator.infinityforreddit.Activity.MainActivity"> + tools:application="ml.docilealligator.infinityforreddit.Activity.SearchResultActivity"> + tools:application="ml.docilealligator.infinityforreddit.Activity.SearchResultActivity"> + tools:application="ml.docilealligator.infinityforreddit.Activity.ViewSubredditDetailActivity"> + tools:application="ml.docilealligator.infinityforreddit.Activity.ViewUserDetailActivity"> + app:fragment="ml.docilealligator.infinityforreddit.Settings.AcknowledgementFragment" /> + app:fragment="ml.docilealligator.infinityforreddit.Settings.CreditsPreferenceFragment" /> + app:fragment="ml.docilealligator.infinityforreddit.Settings.NotificationPreferenceFragment" /> + app:fragment="ml.docilealligator.infinityforreddit.Settings.FontSizePreferenceFragment" /> + app:fragment="ml.docilealligator.infinityforreddit.Settings.AboutPreferenceFragment" /> \ No newline at end of file -- cgit v1.2.3