From 90f741e9e110e408a8f37290e074cb250ac664fd Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Fri, 3 Jul 2020 21:48:35 +0800 Subject: Add more themeing options for links, private messages, etc. Restructure class files. --- .../Activity/CommentActivity.java | 8 +- .../infinityforreddit/Activity/InboxActivity.java | 6 +- .../infinityforreddit/Activity/MainActivity.java | 2 +- .../Activity/ViewPostDetailActivity.java | 22 +- .../Activity/ViewPrivateMessagesActivity.java | 6 +- .../Activity/ViewSubredditDetailActivity.java | 2 +- .../Activity/ViewUserDetailActivity.java | 2 +- .../Adapter/CommentAndPostRecyclerViewAdapter.java | 111 +++--- .../CommentsListingRecyclerViewAdapter.java | 47 +-- .../Adapter/MessageRecyclerViewAdapter.java | 16 +- .../PrivateMessagesDetailRecyclerViewAdapter.java | 2 +- .../Adapter/RulesRecyclerViewAdapter.java | 6 + .../CommentMoreBottomSheetFragment.java | 32 +- .../infinityforreddit/Comment/Comment.java | 386 +++++++++++++++++++++ .../Comment/CommentDataSource.java | 271 +++++++++++++++ .../Comment/CommentDataSourceFactory.java | 56 +++ .../Comment/CommentViewModel.java | 105 ++++++ .../infinityforreddit/Comment/FetchComment.java | 138 ++++++++ .../infinityforreddit/Comment/ParseComment.java | 322 +++++++++++++++++ .../infinityforreddit/Comment/SendComment.java | 64 ++++ .../infinityforreddit/CommentData.java | 386 --------------------- .../infinityforreddit/CommentDataSource.java | 269 -------------- .../CommentDataSourceFactory.java | 55 --- .../infinityforreddit/CommentViewModel.java | 103 ------ .../infinityforreddit/CustomTheme/CustomTheme.java | 138 +++++--- .../CustomTheme/CustomThemeSettingsItem.java | 32 ++ .../CustomTheme/CustomThemeWrapper.java | 128 +++++++ .../Event/RepliedToPrivateMessageEvent.java | 2 +- .../infinityforreddit/FetchComment.java | 138 -------- .../infinityforreddit/FetchMessages.java | 53 --- .../infinityforreddit/FetchRemovedComment.java | 11 +- .../Fragment/CommentsListingFragment.java | 2 +- .../infinityforreddit/Fragment/InboxFragment.java | 8 +- .../Fragment/SidebarFragment.java | 7 + .../docilealligator/infinityforreddit/Message.java | 213 ------------ .../infinityforreddit/Message/FetchMessage.java | 53 +++ .../infinityforreddit/Message/Message.java | 213 ++++++++++++ .../Message/MessageDataSource.java | 119 +++++++ .../Message/MessageDataSourceFactory.java | 47 +++ .../Message/MessageViewModel.java | 97 ++++++ .../infinityforreddit/Message/ParseMessage.java | 205 +++++++++++ .../infinityforreddit/Message/ReadMessage.java | 43 +++ .../infinityforreddit/Message/ReplyMessage.java | 58 ++++ .../infinityforreddit/MessageDataSource.java | 118 ------- .../MessageDataSourceFactory.java | 47 --- .../infinityforreddit/MessageViewModel.java | 96 ----- .../infinityforreddit/ParseComment.java | 322 ----------------- .../infinityforreddit/ParseMessage.java | 205 ----------- .../infinityforreddit/PullNotificationWorker.java | 7 +- .../infinityforreddit/ReadMessage.java | 43 --- .../infinityforreddit/RedditDataRoomDatabase.java | 27 +- .../infinityforreddit/ReplyMessage.java | 58 ---- .../infinityforreddit/SendComment.java | 64 ---- .../Utils/CustomThemeSharedPreferencesUtils.java | 8 + .../res/layout/item_comment_fully_collapsed.xml | 2 +- app/src/main/res/values/strings.xml | 16 + 56 files changed, 2641 insertions(+), 2356 deletions(-) create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Comment/Comment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Comment/CommentDataSource.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Comment/CommentDataSourceFactory.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Comment/CommentViewModel.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Comment/FetchComment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Comment/ParseComment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Comment/SendComment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/CommentData.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSource.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSourceFactory.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/CommentViewModel.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/FetchMessages.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Message.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Message/FetchMessage.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Message/Message.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Message/MessageDataSource.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Message/MessageDataSourceFactory.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Message/MessageViewModel.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Message/ParseMessage.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Message/ReadMessage.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Message/ReplyMessage.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/MessageDataSource.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/MessageDataSourceFactory.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/MessageViewModel.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ParseMessage.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ReadMessage.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/ReplyMessage.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/SendComment.java (limited to 'app') diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/CommentActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/CommentActivity.java index c87fd263..8eeb0a07 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/CommentActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/CommentActivity.java @@ -49,14 +49,14 @@ import io.noties.markwon.recycler.table.TableEntryPlugin; import io.noties.markwon.simple.ext.SimpleExtPlugin; import io.noties.markwon.urlprocessor.UrlProcessorRelativeToAbsolute; import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; -import ml.docilealligator.infinityforreddit.CommentData; +import ml.docilealligator.infinityforreddit.Comment.Comment; import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; import ml.docilealligator.infinityforreddit.BottomSheetFragment.CopyTextBottomSheetFragment; import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; -import ml.docilealligator.infinityforreddit.SendComment; +import ml.docilealligator.infinityforreddit.Comment.SendComment; import ml.docilealligator.infinityforreddit.Utils.SharedPreferencesUtils; import ml.docilealligator.infinityforreddit.Utils.Utils; import retrofit2.Retrofit; @@ -330,13 +330,13 @@ public class CommentActivity extends BaseActivity { mAccessToken, new SendComment.SendCommentListener() { @Override - public void sendCommentSuccess(CommentData commentData) { + public void sendCommentSuccess(Comment comment) { isSubmitting = false; item.setEnabled(true); item.getIcon().setAlpha(255); Toast.makeText(CommentActivity.this, R.string.send_comment_success, Toast.LENGTH_SHORT).show(); Intent returnIntent = new Intent(); - returnIntent.putExtra(RETURN_EXTRA_COMMENT_DATA_KEY, commentData); + returnIntent.putExtra(RETURN_EXTRA_COMMENT_DATA_KEY, comment); returnIntent.putExtra(EXTRA_PARENT_FULLNAME_KEY, parentFullname); if (isReplying) { returnIntent.putExtra(EXTRA_PARENT_POSITION_KEY, parentPosition); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/InboxActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/InboxActivity.java index 66072a2b..fa62c47c 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/InboxActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/InboxActivity.java @@ -38,7 +38,7 @@ import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask import ml.docilealligator.infinityforreddit.AsyncTask.SwitchAccountAsyncTask; import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; -import ml.docilealligator.infinityforreddit.FetchMessages; +import ml.docilealligator.infinityforreddit.Message.FetchMessage; import ml.docilealligator.infinityforreddit.Fragment.InboxFragment; import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.R; @@ -280,14 +280,14 @@ public class InboxActivity extends BaseActivity implements ActivityToolbarInterf InboxFragment fragment = new InboxFragment(); Bundle bundle = new Bundle(); bundle.putString(InboxFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - bundle.putString(InboxFragment.EXTRA_MESSAGE_WHERE, FetchMessages.WHERE_INBOX); + bundle.putString(InboxFragment.EXTRA_MESSAGE_WHERE, FetchMessage.WHERE_INBOX); fragment.setArguments(bundle); return fragment; } else { InboxFragment fragment = new InboxFragment(); Bundle bundle = new Bundle(); bundle.putString(InboxFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - bundle.putString(InboxFragment.EXTRA_MESSAGE_WHERE, FetchMessages.WHERE_MESSAGES); + bundle.putString(InboxFragment.EXTRA_MESSAGE_WHERE, FetchMessage.WHERE_MESSAGES); fragment.setArguments(bundle); return fragment; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java index 04c1ff41..824a686d 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java @@ -82,7 +82,7 @@ import ml.docilealligator.infinityforreddit.ParseAndSaveAccountInfo; import ml.docilealligator.infinityforreddit.Post.PostDataSource; import ml.docilealligator.infinityforreddit.PullNotificationWorker; import ml.docilealligator.infinityforreddit.R; -import ml.docilealligator.infinityforreddit.ReadMessage; +import ml.docilealligator.infinityforreddit.Message.ReadMessage; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; import ml.docilealligator.infinityforreddit.SortType; import ml.docilealligator.infinityforreddit.SortTypeSelectionCallback; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java index 6586dd08..000e677d 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java @@ -62,7 +62,7 @@ import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask import ml.docilealligator.infinityforreddit.AsyncTask.SwitchAccountAsyncTask; import ml.docilealligator.infinityforreddit.BottomSheetFragment.FlairBottomSheetFragment; import ml.docilealligator.infinityforreddit.BottomSheetFragment.PostCommentSortTypeBottomSheetFragment; -import ml.docilealligator.infinityforreddit.CommentData; +import ml.docilealligator.infinityforreddit.Comment.Comment; import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.CustomView.CustomToroContainer; import ml.docilealligator.infinityforreddit.DeleteThing; @@ -72,18 +72,18 @@ import ml.docilealligator.infinityforreddit.Event.ChangeWifiStatusEvent; import ml.docilealligator.infinityforreddit.Event.PostUpdateEventToDetailActivity; import ml.docilealligator.infinityforreddit.Event.PostUpdateEventToPostList; import ml.docilealligator.infinityforreddit.Event.SwitchAccountEvent; -import ml.docilealligator.infinityforreddit.FetchComment; +import ml.docilealligator.infinityforreddit.Comment.FetchComment; import ml.docilealligator.infinityforreddit.FetchRemovedComment; import ml.docilealligator.infinityforreddit.FetchRemovedPost; import ml.docilealligator.infinityforreddit.Flair; import ml.docilealligator.infinityforreddit.Infinity; -import ml.docilealligator.infinityforreddit.ParseComment; +import ml.docilealligator.infinityforreddit.Comment.ParseComment; import ml.docilealligator.infinityforreddit.Post.FetchPost; import ml.docilealligator.infinityforreddit.Post.HidePost; import ml.docilealligator.infinityforreddit.Post.ParsePost; import ml.docilealligator.infinityforreddit.Post.Post; import ml.docilealligator.infinityforreddit.R; -import ml.docilealligator.infinityforreddit.ReadMessage; +import ml.docilealligator.infinityforreddit.Message.ReadMessage; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; import ml.docilealligator.infinityforreddit.SaveThing; import ml.docilealligator.infinityforreddit.SortType; @@ -126,7 +126,7 @@ public class ViewPostDetailActivity extends BaseActivity implements FlairBottomS @State boolean isSingleCommentThreadMode = false; @State - ArrayList comments; + ArrayList comments; @State ArrayList children; @State @@ -648,7 +648,7 @@ public class ViewPostDetailActivity extends BaseActivity implements FlairBottomS ParseComment.parseComment(response.body(), new ArrayList<>(), mLocale, mExpandChildren, new ParseComment.ParseCommentListener() { @Override - public void onParseCommentSuccess(ArrayList expandedComments, String parentId, ArrayList moreChildrenFullnames) { + public void onParseCommentSuccess(ArrayList expandedComments, String parentId, ArrayList moreChildrenFullnames) { ViewPostDetailActivity.this.children = moreChildrenFullnames; hasMoreChildren = children.size() != 0; @@ -738,7 +738,7 @@ public class ViewPostDetailActivity extends BaseActivity implements FlairBottomS FetchComment.fetchComments(retrofit, mAccessToken, mPost.getId(), commentId, sortType, mExpandChildren, mLocale, new FetchComment.FetchCommentListener() { @Override - public void onFetchCommentSuccess(ArrayList expandedComments, + public void onFetchCommentSuccess(ArrayList expandedComments, String parentId, ArrayList children) { if (checkSortState && isSortingComments) { if (changeRefreshState) { @@ -840,7 +840,7 @@ public class ViewPostDetailActivity extends BaseActivity implements FlairBottomS FetchComment.fetchMoreComment(retrofit, mAccessToken, children, mChildrenStartingIndex, 0, mExpandChildren, mLocale, new FetchComment.FetchMoreCommentListener() { @Override - public void onFetchMoreCommentSuccess(ArrayList expandedComments, int childrenStartingIndex) { + public void onFetchMoreCommentSuccess(ArrayList expandedComments, int childrenStartingIndex) { hasMoreChildren = childrenStartingIndex < children.size(); mAdapter.addComments(expandedComments, hasMoreChildren); mChildrenStartingIndex = childrenStartingIndex; @@ -1091,14 +1091,14 @@ public class ViewPostDetailActivity extends BaseActivity implements FlairBottomS .show(); } - public void showRemovedComment(CommentData comment, int position) { + public void showRemovedComment(Comment comment, int position) { Toast.makeText(ViewPostDetailActivity.this, R.string.fetching_removed_comment, Toast.LENGTH_SHORT).show(); FetchRemovedComment.fetchRemovedComment( pushshiftRetrofit, comment, new FetchRemovedComment.FetchRemovedCommentListener() { @Override - public void fetchSuccess(CommentData comment) { + public void fetchSuccess(Comment comment) { mAdapter.editComment(comment.getAuthor(), comment.getCommentMarkdown(), position); } @@ -1451,7 +1451,7 @@ public class ViewPostDetailActivity extends BaseActivity implements FlairBottomS if (requestCode == WRITE_COMMENT_REQUEST_CODE) { if (data != null && resultCode == RESULT_OK) { if (data.hasExtra(RETURN_EXTRA_COMMENT_DATA_KEY)) { - CommentData comment = data.getParcelableExtra(RETURN_EXTRA_COMMENT_DATA_KEY); + Comment comment = data.getParcelableExtra(RETURN_EXTRA_COMMENT_DATA_KEY); if (comment != null && comment.getDepth() == 0) { mAdapter.addComment(comment); } else { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPrivateMessagesActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPrivateMessagesActivity.java index b75f9e8b..e78cdc47 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPrivateMessagesActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPrivateMessagesActivity.java @@ -39,11 +39,11 @@ import ml.docilealligator.infinityforreddit.AsyncTask.LoadUserDataAsyncTask; import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.Event.RepliedToPrivateMessageEvent; import ml.docilealligator.infinityforreddit.Infinity; -import ml.docilealligator.infinityforreddit.Message; +import ml.docilealligator.infinityforreddit.Message.Message; import ml.docilealligator.infinityforreddit.R; -import ml.docilealligator.infinityforreddit.ReadMessage; +import ml.docilealligator.infinityforreddit.Message.ReadMessage; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; -import ml.docilealligator.infinityforreddit.ReplyMessage; +import ml.docilealligator.infinityforreddit.Message.ReplyMessage; import ml.docilealligator.infinityforreddit.Utils.SharedPreferencesUtils; import retrofit2.Retrofit; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java index 2b516549..aa42d49a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java @@ -73,7 +73,7 @@ import ml.docilealligator.infinityforreddit.FragmentCommunicator; import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.Post.PostDataSource; import ml.docilealligator.infinityforreddit.R; -import ml.docilealligator.infinityforreddit.ReadMessage; +import ml.docilealligator.infinityforreddit.Message.ReadMessage; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; import ml.docilealligator.infinityforreddit.SortType; import ml.docilealligator.infinityforreddit.SortTypeSelectionCallback; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java index cbcd54be..8134ebcf 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewUserDetailActivity.java @@ -70,7 +70,7 @@ import ml.docilealligator.infinityforreddit.FragmentCommunicator; import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.Post.PostDataSource; import ml.docilealligator.infinityforreddit.R; -import ml.docilealligator.infinityforreddit.ReadMessage; +import ml.docilealligator.infinityforreddit.Message.ReadMessage; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; import ml.docilealligator.infinityforreddit.SortType; import ml.docilealligator.infinityforreddit.SortTypeSelectionCallback; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java index cb3bc599..f815b3c6 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java @@ -69,6 +69,7 @@ import im.ene.toro.widget.Container; import io.noties.markwon.AbstractMarkwonPlugin; import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; +import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; import io.noties.markwon.linkify.LinkifyPlugin; import io.noties.markwon.recycler.MarkwonAdapter; @@ -91,11 +92,11 @@ import ml.docilealligator.infinityforreddit.AsyncTask.LoadUserDataAsyncTask; import ml.docilealligator.infinityforreddit.BottomSheetFragment.CommentMoreBottomSheetFragment; import ml.docilealligator.infinityforreddit.BottomSheetFragment.CopyTextBottomSheetFragment; import ml.docilealligator.infinityforreddit.BottomSheetFragment.ShareLinkBottomSheetFragment; -import ml.docilealligator.infinityforreddit.CommentData; +import ml.docilealligator.infinityforreddit.Comment.Comment; +import ml.docilealligator.infinityforreddit.Comment.FetchComment; import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.CustomView.AspectRatioGifImageView; import ml.docilealligator.infinityforreddit.CustomView.MarkwonLinearLayoutManager; -import ml.docilealligator.infinityforreddit.FetchComment; import ml.docilealligator.infinityforreddit.Post.Post; import ml.docilealligator.infinityforreddit.Post.PostDataSource; import ml.docilealligator.infinityforreddit.R; @@ -138,7 +139,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter mVisibleComments; + private ArrayList mVisibleComments; private String mSubredditNamePrefixed; private Locale mLocale; private String mSingleCommentId; @@ -205,6 +206,8 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter= 0) { - CommentData parentComment = mVisibleComments.get(parentPosition); + Comment parentComment = mVisibleComments.get(parentPosition); mVisibleComments.get(commentPosition).setLoadingMoreChildren(true); mVisibleComments.get(commentPosition).setLoadMoreChildrenFailed(false); @@ -1014,7 +1032,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter expandedComments, + public void onFetchMoreCommentSuccess(ArrayList expandedComments, int childrenStartingIndex) { if (mVisibleComments.size() > parentPosition && parentComment.getFullName().equals(mVisibleComments.get(parentPosition).getFullName())) { @@ -1287,7 +1305,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter comments, ArrayList newList, int position) { + private void expandChildren(ArrayList comments, ArrayList newList, int position) { if (comments != null && comments.size() > 0) { newList.addAll(position, comments); for (int i = 0; i < comments.size(); i++) { @@ -1327,7 +1345,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter comments, boolean hasMoreComments) { + public void addComments(@NonNull ArrayList comments, boolean hasMoreComments) { if (mVisibleComments.size() == 0) { isInitiallyLoading = false; isInitiallyLoadingFailed = false; @@ -1364,7 +1382,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter newList = new ArrayList<>(); + ArrayList newList = new ArrayList<>(); expandChildren(mVisibleComments.get(parentPosition).getChildren(), newList, 0); mVisibleComments.get(parentPosition).setExpanded(true); mVisibleComments.addAll(parentPosition + 1, newList); @@ -1417,7 +1435,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter getVisibleComments() { + public ArrayList getVisibleComments() { return mVisibleComments; } @@ -2799,7 +2817,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter authorTextView.performClick()); moreButton.setOnClickListener(view -> { - CommentData comment = getCurrentComment(this); + Comment comment = getCurrentComment(this); Bundle bundle = new Bundle(); if (!mPost.isArchived() && !mPost.isLocked() && comment.getAuthor().equals(mAccountName)) { bundle.putString(CommentMoreBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); @@ -2831,7 +2849,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter { - CommentData comment = getCurrentComment(this); + Comment comment = getCurrentComment(this); if (comment.isSaved()) { comment.setSaved(false); SaveThing.unsaveThing(mOauthRetrofit, mAccessToken, comment.getFullName(), new SaveThing.SaveThingListener() { @@ -3018,13 +3036,13 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter= 0 && commentPosition < mVisibleComments.size()) { - CommentData comment = getCurrentComment(this); + Comment comment = getCurrentComment(this); if (mVisibleComments.get(commentPosition).isExpanded()) { collapseChildren(commentPosition); expandButton.setImageResource(R.drawable.ic_expand_more_grey_24dp); } else { comment.setExpanded(true); - ArrayList newList = new ArrayList<>(); + ArrayList newList = new ArrayList<>(); expandChildren(mVisibleComments.get(commentPosition).getChildren(), newList, 0); mVisibleComments.get(commentPosition).setExpanded(true); mVisibleComments.addAll(commentPosition + 1, newList); @@ -3082,8 +3100,8 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter { int commentPosition = mIsSingleCommentThreadMode ? getAdapterPosition() - 2 : getAdapterPosition() - 1; if (commentPosition >= 0 && commentPosition < mVisibleComments.size()) { - CommentData comment = getCurrentComment(this); + Comment comment = getCurrentComment(this); comment.setExpanded(true); - ArrayList newList = new ArrayList<>(); + ArrayList newList = new ArrayList<>(); expandChildren(mVisibleComments.get(commentPosition).getChildren(), newList, 0); mVisibleComments.get(commentPosition).setExpanded(true); mVisibleComments.addAll(commentPosition + 1, newList); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentsListingRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentsListingRecyclerViewAdapter.java index f58da947..eb3ef3f2 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentsListingRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentsListingRecyclerViewAdapter.java @@ -33,6 +33,7 @@ import butterknife.ButterKnife; import io.noties.markwon.AbstractMarkwonPlugin; import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; +import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; import io.noties.markwon.linkify.LinkifyPlugin; import io.noties.markwon.simple.ext.SimpleExtPlugin; @@ -41,7 +42,7 @@ import ml.docilealligator.infinityforreddit.Activity.ViewPostDetailActivity; import ml.docilealligator.infinityforreddit.Activity.ViewSubredditDetailActivity; import ml.docilealligator.infinityforreddit.Activity.ViewUserDetailActivity; import ml.docilealligator.infinityforreddit.BottomSheetFragment.CommentMoreBottomSheetFragment; -import ml.docilealligator.infinityforreddit.CommentData; +import ml.docilealligator.infinityforreddit.Comment.Comment; import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.NetworkState; import ml.docilealligator.infinityforreddit.R; @@ -52,19 +53,19 @@ import ml.docilealligator.infinityforreddit.Utils.Utils; import ml.docilealligator.infinityforreddit.VoteThing; import retrofit2.Retrofit; -public class CommentsListingRecyclerViewAdapter extends PagedListAdapter { +public class CommentsListingRecyclerViewAdapter 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 static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() { + 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()); + public boolean areItemsTheSame(@NonNull Comment comment, @NonNull Comment t1) { + return comment.getId().equals(t1.getId()); } @Override - public boolean areContentsTheSame(@NonNull CommentData commentData, @NonNull CommentData t1) { - return commentData.getCommentMarkdown().equals(t1.getCommentMarkdown()); + public boolean areContentsTheSame(@NonNull Comment comment, @NonNull Comment t1) { + return comment.getCommentMarkdown().equals(t1.getCommentMarkdown()); } }; private Context mContext; @@ -103,6 +104,11 @@ public class CommentsListingRecyclerViewAdapter extends PagedListAdapter { @@ -115,6 +121,7 @@ public class CommentsListingRecyclerViewAdapter extends PagedListAdapter { @@ -104,10 +104,10 @@ public class MessageRecyclerViewAdapter extends PagedListAdapter { - if (mMessageType == FetchMessages.MESSAGE_TYPE_INBOX + if (mMessageType == FetchMessage.MESSAGE_TYPE_INBOX && 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); - } else if (mMessageType == FetchMessages.MESSAGE_TYPE_PRIVATE_MESSAGE) { + } else if (mMessageType == FetchMessage.MESSAGE_TYPE_PRIVATE_MESSAGE) { Intent intent = new Intent(mContext, ViewPrivateMessagesActivity.class); intent.putExtra(ViewPrivateMessagesActivity.EXTRA_PRIVATE_MESSAGE, message); intent.putExtra(ViewPrivateMessagesActivity.EXTRA_MESSAGE_POSITION, holder.getAdapterPosition()); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PrivateMessagesDetailRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PrivateMessagesDetailRecyclerViewAdapter.java index 7cbf73a1..5bcbba8a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PrivateMessagesDetailRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PrivateMessagesDetailRecyclerViewAdapter.java @@ -34,7 +34,7 @@ import ml.docilealligator.infinityforreddit.Activity.LinkResolverActivity; import ml.docilealligator.infinityforreddit.Activity.ViewPrivateMessagesActivity; import ml.docilealligator.infinityforreddit.Activity.ViewUserDetailActivity; import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper; -import ml.docilealligator.infinityforreddit.Message; +import ml.docilealligator.infinityforreddit.Message.Message; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.Utils.SharedPreferencesUtils; import ml.docilealligator.infinityforreddit.Utils.Utils; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/RulesRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/RulesRecyclerViewAdapter.java index 5d23975d..2b5e62df 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/RulesRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/RulesRecyclerViewAdapter.java @@ -20,6 +20,7 @@ import butterknife.ButterKnife; import io.noties.markwon.AbstractMarkwonPlugin; import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; +import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; import io.noties.markwon.linkify.LinkifyPlugin; import io.noties.markwon.simple.ext.SimpleExtPlugin; @@ -50,6 +51,11 @@ public class RulesRecyclerViewAdapter extends RecyclerView.Adapter { Intent intent = new Intent(activity, EditCommentActivity.class); intent.putExtra(EditCommentActivity.EXTRA_ACCESS_TOKEN, accessToken); - intent.putExtra(EditCommentActivity.EXTRA_FULLNAME, commentData.getFullName()); - intent.putExtra(EditCommentActivity.EXTRA_CONTENT, commentData.getCommentMarkdown()); + intent.putExtra(EditCommentActivity.EXTRA_FULLNAME, comment.getFullName()); + intent.putExtra(EditCommentActivity.EXTRA_CONTENT, comment.getCommentMarkdown()); intent.putExtra(EditCommentActivity.EXTRA_POSITION, bundle.getInt(EXTRA_POSITION)); if (activity instanceof ViewPostDetailActivity) { activity.startActivityForResult(intent, ViewPostDetailActivity.EDIT_COMMENT_REQUEST_CODE); @@ -96,9 +96,9 @@ public class CommentMoreBottomSheetFragment extends RoundedBottomSheetDialogFrag deleteTextView.setOnClickListener(view -> { dismiss(); if (activity instanceof ViewPostDetailActivity) { - ((ViewPostDetailActivity) activity).deleteComment(commentData.getFullName(), bundle.getInt(EXTRA_POSITION)); + ((ViewPostDetailActivity) activity).deleteComment(comment.getFullName(), bundle.getInt(EXTRA_POSITION)); } else if (activity instanceof ViewUserDetailActivity) { - ((ViewUserDetailActivity) activity).deleteComment(commentData.getFullName()); + ((ViewUserDetailActivity) activity).deleteComment(comment.getFullName()); } }); } @@ -108,7 +108,7 @@ public class CommentMoreBottomSheetFragment extends RoundedBottomSheetDialogFrag try { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); - intent.putExtra(Intent.EXTRA_TEXT, commentData.getPermalink()); + intent.putExtra(Intent.EXTRA_TEXT, comment.getPermalink()); activity.startActivity(Intent.createChooser(intent, getString(R.string.share))); } catch (ActivityNotFoundException e) { Toast.makeText(activity, R.string.no_activity_found_for_share, Toast.LENGTH_SHORT).show(); @@ -119,31 +119,31 @@ public class CommentMoreBottomSheetFragment extends RoundedBottomSheetDialogFrag dismiss(); CopyTextBottomSheetFragment copyTextBottomSheetFragment = new CopyTextBottomSheetFragment(); Bundle copyBundle = new Bundle(); - copyBundle.putString(CopyTextBottomSheetFragment.EXTRA_MARKDOWN, commentData.getCommentMarkdown()); - copyBundle.putString(CopyTextBottomSheetFragment.EXTRA_RAW_TEXT, commentData.getCommentRawText()); + copyBundle.putString(CopyTextBottomSheetFragment.EXTRA_MARKDOWN, comment.getCommentMarkdown()); + copyBundle.putString(CopyTextBottomSheetFragment.EXTRA_RAW_TEXT, comment.getCommentRawText()); copyTextBottomSheetFragment.setArguments(copyBundle); copyTextBottomSheetFragment.show(activity.getSupportFragmentManager(), copyTextBottomSheetFragment.getTag()); }); reportTextView.setOnClickListener(view -> { Intent intent = new Intent(activity, ReportActivity.class); - intent.putExtra(ReportActivity.EXTRA_SUBREDDIT_NAME, commentData.getSubredditName()); - intent.putExtra(ReportActivity.EXTRA_THING_FULLNAME, commentData.getFullName()); + intent.putExtra(ReportActivity.EXTRA_SUBREDDIT_NAME, comment.getSubredditName()); + intent.putExtra(ReportActivity.EXTRA_THING_FULLNAME, comment.getFullName()); activity.startActivity(intent); dismiss(); }); - if ("[deleted]".equals(commentData.getAuthor()) || - "[deleted]".equals(commentData.getCommentRawText()) || - "[removed]".equals(commentData.getCommentRawText()) + if ("[deleted]".equals(comment.getAuthor()) || + "[deleted]".equals(comment.getCommentRawText()) || + "[removed]".equals(comment.getCommentRawText()) ) { seeRemovedTextView.setVisibility(View.VISIBLE); seeRemovedTextView.setOnClickListener(view -> { dismiss(); if (activity instanceof ViewPostDetailActivity) { - ((ViewPostDetailActivity) activity).showRemovedComment(commentData, bundle.getInt(EXTRA_POSITION)); + ((ViewPostDetailActivity) activity).showRemovedComment(comment, bundle.getInt(EXTRA_POSITION)); } }); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/Comment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/Comment.java new file mode 100644 index 00000000..5d27a3a1 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/Comment.java @@ -0,0 +1,386 @@ +package ml.docilealligator.infinityforreddit.Comment; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; + +import ml.docilealligator.infinityforreddit.Utils.APIUtils; + +public class Comment 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; + public static final Creator CREATOR = new Creator() { + @Override + public Comment createFromParcel(Parcel in) { + return new Comment(in); + } + + @Override + public Comment[] newArray(int size) { + return new Comment[size]; + } + }; + private String id; + private String fullName; + private String author; + private String authorFlair; + private String authorFlairHTML; + private String linkAuthor; + private long commentTimeMillis; + private String commentMarkdown; + private String commentRawText; + private String linkId; + private String subredditName; + private String parentId; + private int score; + private int voteType; + private boolean isSubmitter; + private String distinguished; + private String permalink; + private String awards; + private int depth; + private boolean collapsed; + private boolean hasReply; + private boolean scoreHidden; + private boolean saved; + private boolean isExpanded; + private boolean hasExpandedBefore; + private ArrayList children; + private ArrayList moreChildrenFullnames; + private int moreChildrenStartingIndex; + private boolean isPlaceHolder; + private boolean isLoadingMoreChildren; + private boolean loadMoreChildrenFailed; + + public Comment(String id, String fullName, String author, String authorFlair, + String authorFlairHTML, String linkAuthor, + long commentTimeMillis, String commentMarkdown, String commentRawText, + String linkId, String subredditName, String parentId, int score, + int voteType, boolean isSubmitter, String distinguished, String permalink, + String awards, int depth, boolean collapsed, boolean hasReply, + boolean scoreHidden, boolean saved) { + this.id = id; + this.fullName = fullName; + this.author = author; + this.authorFlair = authorFlair; + this.authorFlairHTML = authorFlairHTML; + this.linkAuthor = linkAuthor; + this.commentTimeMillis = commentTimeMillis; + this.commentMarkdown = commentMarkdown; + this.commentRawText = commentRawText; + this.linkId = linkId; + this.subredditName = subredditName; + this.parentId = parentId; + this.score = score; + this.voteType = voteType; + this.isSubmitter = isSubmitter; + this.distinguished = distinguished; + this.permalink = APIUtils.API_BASE_URI + permalink; + this.awards = awards; + this.depth = depth; + this.collapsed = collapsed; + this.hasReply = hasReply; + this.scoreHidden = scoreHidden; + this.saved = saved; + this.isExpanded = false; + this.hasExpandedBefore = false; + moreChildrenStartingIndex = 0; + isPlaceHolder = false; + } + + public Comment(String parentFullName, int depth) { + this.fullName = parentFullName; + this.depth = depth; + isPlaceHolder = true; + isLoadingMoreChildren = false; + loadMoreChildrenFailed = false; + } + + protected Comment(Parcel in) { + id = in.readString(); + fullName = in.readString(); + author = in.readString(); + authorFlair = in.readString(); + authorFlairHTML = in.readString(); + linkAuthor = in.readString(); + commentTimeMillis = in.readLong(); + commentMarkdown = in.readString(); + commentRawText = in.readString(); + linkId = in.readString(); + subredditName = in.readString(); + parentId = in.readString(); + score = in.readInt(); + voteType = in.readInt(); + isSubmitter = in.readByte() != 0; + distinguished = in.readString(); + permalink = in.readString(); + awards = in.readString(); + depth = in.readInt(); + collapsed = in.readByte() != 0; + hasReply = in.readByte() != 0; + scoreHidden = in.readByte() != 0; + isExpanded = in.readByte() != 0; + hasExpandedBefore = in.readByte() != 0; + children = in.readArrayList(Comment.class.getClassLoader()); + moreChildrenFullnames = in.readArrayList(Comment.class.getClassLoader()); + moreChildrenStartingIndex = in.readInt(); + isPlaceHolder = in.readByte() != 0; + isLoadingMoreChildren = in.readByte() != 0; + loadMoreChildrenFailed = in.readByte() != 0; + } + + public String getId() { + return id; + } + + public String getFullName() { + return fullName; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getAuthorFlair() { + return authorFlair; + } + + public String getAuthorFlairHTML() { + return authorFlairHTML; + } + + public String getLinkAuthor() { + return linkAuthor; + } + + public long getCommentTimeMillis() { + return commentTimeMillis; + } + + public String getCommentMarkdown() { + return commentMarkdown; + } + + public void setCommentMarkdown(String commentMarkdown) { + this.commentMarkdown = commentMarkdown; + } + + public String getCommentRawText() { + return commentRawText; + } + + public void setCommentRawText(String commentRawText) { + this.commentRawText = commentRawText; + } + + public String getLinkId() { + return linkId; + } + + public String getSubredditName() { + return subredditName; + } + + public String getParentId() { + return parentId; + } + + public void setParentId(String parentId) { + this.parentId = parentId; + } + + public int getScore() { + return score; + } + + public void setScore(int score) { + this.score = score; + } + + public boolean isSubmitter() { + return isSubmitter; + } + + public boolean isModerator() { + return distinguished != null && distinguished.equals("moderator"); + } + + public String getPermalink() { + return permalink; + } + + public String getAwards() { + return awards; + } + + public int getDepth() { + return depth; + } + + public boolean isCollapsed() { + return collapsed; + } + + public boolean hasReply() { + return hasReply; + } + + public void setHasReply(boolean hasReply) { + this.hasReply = hasReply; + } + + public boolean isScoreHidden() { + return scoreHidden; + } + + public boolean isSaved() { + return saved; + } + + public void setSaved(boolean saved) { + this.saved = saved; + } + + public boolean isExpanded() { + return isExpanded; + } + + public void setExpanded(boolean isExpanded) { + this.isExpanded = isExpanded; + if (isExpanded && !hasExpandedBefore) { + hasExpandedBefore = true; + } + } + + public boolean hasExpandedBefore() { + return hasExpandedBefore; + } + + public int getVoteType() { + return voteType; + } + + public void setVoteType(int voteType) { + this.voteType = voteType; + } + + public ArrayList getChildren() { + return children; + } + + public void setChildren(ArrayList children) { + this.children = children; + } + + public void addChildren(ArrayList moreChildren) { + if (children == null || children.size() == 0) { + setChildren(moreChildren); + } else { + if (children.size() > 1 && children.get(children.size() - 1).isPlaceHolder) { + children.addAll(children.size() - 2, moreChildren); + } else { + children.addAll(moreChildren); + } + } + } + + public void addChild(Comment comment) { + addChild(comment, 0); + } + + public void addChild(Comment comment, int position) { + if (children == null) { + children = new ArrayList<>(); + } + children.add(position, comment); + } + + public ArrayList getMoreChildrenFullnames() { + return moreChildrenFullnames; + } + + public void setMoreChildrenFullnames(ArrayList moreChildrenFullnames) { + this.moreChildrenFullnames = moreChildrenFullnames; + } + + public boolean hasMoreChildrenFullnames() { + return moreChildrenFullnames != null; + } + + public void removeMoreChildrenFullnames() { + moreChildrenFullnames.clear(); + } + + public int getMoreChildrenStartingIndex() { + return moreChildrenStartingIndex; + } + + public void setMoreChildrenStartingIndex(int moreChildrenStartingIndex) { + this.moreChildrenStartingIndex = moreChildrenStartingIndex; + } + + public boolean isPlaceHolder() { + return isPlaceHolder; + } + + public boolean isLoadingMoreChildren() { + return isLoadingMoreChildren; + } + + public void setLoadingMoreChildren(boolean isLoadingMoreChildren) { + this.isLoadingMoreChildren = isLoadingMoreChildren; + } + + public boolean isLoadMoreChildrenFailed() { + return loadMoreChildrenFailed; + } + + public void setLoadMoreChildrenFailed(boolean loadMoreChildrenFailed) { + this.loadMoreChildrenFailed = loadMoreChildrenFailed; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int i) { + parcel.writeString(id); + parcel.writeString(fullName); + parcel.writeString(author); + parcel.writeString(authorFlair); + parcel.writeString(authorFlairHTML); + parcel.writeString(linkAuthor); + parcel.writeLong(commentTimeMillis); + parcel.writeString(commentMarkdown); + parcel.writeString(commentRawText); + parcel.writeString(linkId); + parcel.writeString(subredditName); + parcel.writeString(parentId); + parcel.writeInt(score); + parcel.writeInt(voteType); + parcel.writeByte((byte) (isSubmitter ? 1 : 0)); + parcel.writeString(distinguished); + parcel.writeString(permalink); + parcel.writeString(awards); + parcel.writeInt(depth); + parcel.writeByte((byte) (collapsed ? 1 : 0)); + parcel.writeByte((byte) (hasReply ? 1 : 0)); + parcel.writeByte((byte) (scoreHidden ? 1 : 0)); + parcel.writeByte((byte) (isExpanded ? 1 : 0)); + parcel.writeByte((byte) (hasExpandedBefore ? 1 : 0)); + parcel.writeList(children); + parcel.writeList(moreChildrenFullnames); + parcel.writeInt(moreChildrenStartingIndex); + parcel.writeByte((byte) (isPlaceHolder ? 1 : 0)); + parcel.writeByte((byte) (isLoadingMoreChildren ? 1 : 0)); + parcel.writeByte((byte) (loadMoreChildrenFailed ? 1 : 0)); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/CommentDataSource.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/CommentDataSource.java new file mode 100644 index 00000000..35a8ddd2 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/CommentDataSource.java @@ -0,0 +1,271 @@ +package ml.docilealligator.infinityforreddit.Comment; + +import android.os.AsyncTask; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.MutableLiveData; +import androidx.paging.PageKeyedDataSource; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Locale; + +import ml.docilealligator.infinityforreddit.API.RedditAPI; +import ml.docilealligator.infinityforreddit.NetworkState; +import ml.docilealligator.infinityforreddit.Post.PostDataSource; +import ml.docilealligator.infinityforreddit.SortType; +import ml.docilealligator.infinityforreddit.Utils.JSONUtils; +import ml.docilealligator.infinityforreddit.Utils.APIUtils; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +public class CommentDataSource extends PageKeyedDataSource { + + private Retrofit retrofit; + private Locale locale; + @Nullable + private String accessToken; + private String username; + private SortType sortType; + private boolean areSavedComments; + + private MutableLiveData paginationNetworkStateLiveData; + private MutableLiveData initialLoadStateLiveData; + private MutableLiveData hasPostLiveData; + + private LoadParams params; + private LoadCallback callback; + + CommentDataSource(Retrofit retrofit, Locale locale, @Nullable String accessToken, String username, SortType sortType, + boolean areSavedComments) { + this.retrofit = retrofit; + this.locale = locale; + this.accessToken = accessToken; + this.username = username; + this.sortType = sortType; + this.areSavedComments = areSavedComments; + paginationNetworkStateLiveData = new MutableLiveData<>(); + initialLoadStateLiveData = new MutableLiveData<>(); + hasPostLiveData = new MutableLiveData<>(); + } + + MutableLiveData getPaginationNetworkStateLiveData() { + return paginationNetworkStateLiveData; + } + + MutableLiveData getInitialLoadStateLiveData() { + return initialLoadStateLiveData; + } + + MutableLiveData hasPostLiveData() { + return hasPostLiveData; + } + + void retryLoadingMore() { + loadAfter(params, callback); + } + + @Override + public void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback callback) { + initialLoadStateLiveData.postValue(NetworkState.LOADING); + + RedditAPI api = retrofit.create(RedditAPI.class); + Call commentsCall; + if (areSavedComments) { + if (sortType.getTime() != null) { + commentsCall = api.getUserSavedCommentsOauth(username, PostDataSource.USER_WHERE_SAVED, + null, sortType.getType().value, sortType.getTime().value, + APIUtils.getOAuthHeader(accessToken)); + } else { + commentsCall = api.getUserSavedCommentsOauth(username, PostDataSource.USER_WHERE_SAVED, + null, sortType.getType().value, APIUtils.getOAuthHeader(accessToken)); + } + } else { + if (accessToken == null) { + if (sortType.getTime() != null) { + commentsCall = api.getUserComments(username, null, sortType.getType().value, + sortType.getTime().value); + } else { + commentsCall = api.getUserComments(username, null, sortType.getType().value); + } + } else { + if (sortType.getTime() != null) { + commentsCall = api.getUserCommentsOauth(APIUtils.getOAuthHeader(accessToken), username, + null, sortType.getType().value, sortType.getTime().value); + } else { + commentsCall = api.getUserCommentsOauth(APIUtils.getOAuthHeader(accessToken), username, + null, sortType.getType().value); + } + } + } + commentsCall.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + new ParseCommentAsyncTask(response.body(), locale, new ParseCommentAsyncTask.ParseCommentAsyncTaskListener() { + @Override + public void parseSuccessful(ArrayList comments, String after) { + if (comments.size() == 0) { + hasPostLiveData.postValue(false); + } else { + hasPostLiveData.postValue(true); + } + + if (after == null || after.equals("") || after.equals("null")) { + callback.onResult(comments, null, null); + } else { + callback.onResult(comments, null, after); + } + initialLoadStateLiveData.postValue(NetworkState.LOADED); + } + + @Override + public void parseFailed() { + initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); + } + }).execute(); + } else { + initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); + } + }); + } + + @Override + public void loadBefore(@NonNull LoadParams params, @NonNull LoadCallback callback) { + + } + + @Override + public void loadAfter(@NonNull LoadParams params, @NonNull LoadCallback callback) { + this.params = params; + this.callback = callback; + + paginationNetworkStateLiveData.postValue(NetworkState.LOADING); + + RedditAPI api = retrofit.create(RedditAPI.class); + Call commentsCall; + if (areSavedComments) { + if (sortType.getTime() != null) { + commentsCall = api.getUserSavedCommentsOauth(username, PostDataSource.USER_WHERE_SAVED, params.key, + sortType.getType().value, sortType.getTime().value, APIUtils.getOAuthHeader(accessToken)); + } else { + commentsCall = api.getUserSavedCommentsOauth(username, PostDataSource.USER_WHERE_SAVED, params.key, + sortType.getType().value, APIUtils.getOAuthHeader(accessToken)); + } + } else { + if (accessToken == null) { + if (sortType.getTime() != null) { + commentsCall = api.getUserComments(username, params.key, sortType.getType().value, + sortType.getTime().value); + } else { + commentsCall = api.getUserComments(username, params.key, sortType.getType().value); + } + } else { + if (sortType.getTime() != null) { + commentsCall = api.getUserCommentsOauth(APIUtils.getOAuthHeader(accessToken), + username, params.key, sortType.getType().value, sortType.getTime().value); + } else { + commentsCall = api.getUserCommentsOauth(APIUtils.getOAuthHeader(accessToken), + username, params.key, sortType.getType().value); + } + } + } + commentsCall.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + new ParseCommentAsyncTask(response.body(), locale, new ParseCommentAsyncTask.ParseCommentAsyncTaskListener() { + @Override + public void parseSuccessful(ArrayList comments, String after) { + if (after == null || after.equals("") || after.equals("null")) { + callback.onResult(comments, null); + } else { + callback.onResult(comments, after); + } + paginationNetworkStateLiveData.postValue(NetworkState.LOADED); + } + + @Override + public void parseFailed() { + paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); + } + }).execute(); + } else { + paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error fetching data")); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error fetching data")); + } + }); + } + + private static class ParseCommentAsyncTask extends AsyncTask, ArrayList> { + private String after; + private Locale locale; + private JSONArray commentsJSONArray; + private boolean parseFailed; + private ParseCommentAsyncTaskListener parseCommentAsyncTaskListener; + + ParseCommentAsyncTask(String response, Locale locale, ParseCommentAsyncTaskListener parseCommentAsyncTaskListener) { + this.locale = locale; + this.parseCommentAsyncTaskListener = parseCommentAsyncTaskListener; + try { + JSONObject data = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY); + commentsJSONArray = data.getJSONArray(JSONUtils.CHILDREN_KEY); + after = data.getString(JSONUtils.AFTER_KEY); + parseFailed = false; + } catch (JSONException e) { + parseFailed = true; + e.printStackTrace(); + } + } + + @Override + protected ArrayList doInBackground(Void... voids) { + if (parseFailed) { + return null; + } + + ArrayList comments = new ArrayList<>(); + for (int i = 0; i < commentsJSONArray.length(); i++) { + try { + JSONObject commentJSON = commentsJSONArray.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY); + comments.add(ParseComment.parseSingleComment(commentJSON, 0, locale)); + } catch (JSONException ignored) { + } + } + return comments; + } + + @Override + protected void onPostExecute(ArrayList commentData) { + super.onPostExecute(commentData); + if (commentData != null) { + parseCommentAsyncTaskListener.parseSuccessful(commentData, after); + } else { + parseCommentAsyncTaskListener.parseFailed(); + } + } + + interface ParseCommentAsyncTaskListener { + void parseSuccessful(ArrayList comments, String after); + + void parseFailed(); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/CommentDataSourceFactory.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/CommentDataSourceFactory.java new file mode 100644 index 00000000..bd7e5831 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/CommentDataSourceFactory.java @@ -0,0 +1,56 @@ +package ml.docilealligator.infinityforreddit.Comment; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.MutableLiveData; +import androidx.paging.DataSource; + +import java.util.Locale; + +import ml.docilealligator.infinityforreddit.SortType; +import retrofit2.Retrofit; + +class CommentDataSourceFactory extends DataSource.Factory { + private Retrofit retrofit; + private Locale locale; + private String accessToken; + private String username; + private SortType sortType; + private boolean areSavedComments; + + private CommentDataSource commentDataSource; + private MutableLiveData commentDataSourceLiveData; + + CommentDataSourceFactory(Retrofit retrofit, Locale locale, @Nullable String accessToken, + String username, SortType sortType, + boolean areSavedComments) { + this.retrofit = retrofit; + this.locale = locale; + this.accessToken = accessToken; + this.username = username; + this.sortType = sortType; + this.areSavedComments = areSavedComments; + commentDataSourceLiveData = new MutableLiveData<>(); + } + + @NonNull + @Override + public DataSource create() { + commentDataSource = new CommentDataSource(retrofit, locale, accessToken, username, sortType, + areSavedComments); + commentDataSourceLiveData.postValue(commentDataSource); + return commentDataSource; + } + + public MutableLiveData getCommentDataSourceLiveData() { + return commentDataSourceLiveData; + } + + CommentDataSource getCommentDataSource() { + return commentDataSource; + } + + void changeSortType(SortType sortType) { + this.sortType = sortType; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/CommentViewModel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/CommentViewModel.java new file mode 100644 index 00000000..99832054 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/CommentViewModel.java @@ -0,0 +1,105 @@ +package ml.docilealligator.infinityforreddit.Comment; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.Transformations; +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; +import androidx.paging.LivePagedListBuilder; +import androidx.paging.PagedList; + +import java.util.Locale; + +import ml.docilealligator.infinityforreddit.NetworkState; +import ml.docilealligator.infinityforreddit.SortType; +import retrofit2.Retrofit; + +public class CommentViewModel extends ViewModel { + private CommentDataSourceFactory commentDataSourceFactory; + private LiveData paginationNetworkState; + private LiveData initialLoadingState; + private LiveData hasCommentLiveData; + private LiveData> comments; + private MutableLiveData sortTypeLiveData; + + public CommentViewModel(Retrofit retrofit, Locale locale, String accessToken, String username, SortType sortType, + boolean areSavedComments) { + commentDataSourceFactory = new CommentDataSourceFactory(retrofit, locale, accessToken, username, sortType, + areSavedComments); + + initialLoadingState = Transformations.switchMap(commentDataSourceFactory.getCommentDataSourceLiveData(), + CommentDataSource::getInitialLoadStateLiveData); + paginationNetworkState = Transformations.switchMap(commentDataSourceFactory.getCommentDataSourceLiveData(), + CommentDataSource::getPaginationNetworkStateLiveData); + hasCommentLiveData = Transformations.switchMap(commentDataSourceFactory.getCommentDataSourceLiveData(), + CommentDataSource::hasPostLiveData); + + sortTypeLiveData = new MutableLiveData<>(); + sortTypeLiveData.postValue(sortType); + + PagedList.Config pagedListConfig = + (new PagedList.Config.Builder()) + .setEnablePlaceholders(false) + .setPageSize(25) + .build(); + + comments = Transformations.switchMap(sortTypeLiveData, sort -> { + commentDataSourceFactory.changeSortType(sortTypeLiveData.getValue()); + return (new LivePagedListBuilder(commentDataSourceFactory, pagedListConfig)).build(); + }); + } + + public LiveData> getComments() { + return comments; + } + + public LiveData getPaginationNetworkState() { + return paginationNetworkState; + } + + public LiveData getInitialLoadingState() { + return initialLoadingState; + } + + public LiveData hasComment() { + return hasCommentLiveData; + } + + public void refresh() { + commentDataSourceFactory.getCommentDataSource().invalidate(); + } + + public void retryLoadingMore() { + commentDataSourceFactory.getCommentDataSource().retryLoadingMore(); + } + + public void changeSortType(SortType sortType) { + sortTypeLiveData.postValue(sortType); + } + + public static class Factory extends ViewModelProvider.NewInstanceFactory { + private Retrofit retrofit; + private Locale locale; + private String accessToken; + private String username; + private SortType sortType; + private boolean areSavedComments; + + public Factory(Retrofit retrofit, Locale locale, String accessToken, String username, + SortType sortType, boolean areSavedComments) { + this.retrofit = retrofit; + this.locale = locale; + this.accessToken = accessToken; + this.username = username; + this.sortType = sortType; + this.areSavedComments = areSavedComments; + } + + @NonNull + @Override + public T create(@NonNull Class modelClass) { + return (T) new CommentViewModel(retrofit, locale, accessToken, username, sortType, areSavedComments); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/FetchComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/FetchComment.java new file mode 100644 index 00000000..361a5746 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/FetchComment.java @@ -0,0 +1,138 @@ +package ml.docilealligator.infinityforreddit.Comment; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.ArrayList; +import java.util.Locale; + +import ml.docilealligator.infinityforreddit.API.RedditAPI; +import ml.docilealligator.infinityforreddit.Utils.APIUtils; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +public class FetchComment { + public static void fetchComments(Retrofit retrofit, @Nullable String accessToken, String article, + String commentId, String sortType, boolean expandChildren, + Locale locale, FetchCommentListener fetchCommentListener) { + RedditAPI api = retrofit.create(RedditAPI.class); + Call comments; + if (accessToken == null) { + if (commentId == null) { + comments = api.getPostAndCommentsById(article, sortType); + } else { + comments = api.getPostAndCommentsSingleThreadById(article, commentId, sortType); + } + } else { + if (commentId == null) { + comments = api.getPostAndCommentsByIdOauth(article, sortType, APIUtils.getOAuthHeader(accessToken)); + } else { + comments = api.getPostAndCommentsSingleThreadByIdOauth(article, commentId, sortType, + APIUtils.getOAuthHeader(accessToken)); + } + } + + comments.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + ParseComment.parseComment(response.body(), new ArrayList<>(), + locale, expandChildren, new ParseComment.ParseCommentListener() { + @Override + public void onParseCommentSuccess(ArrayList expandedComments, + String parentId, ArrayList moreChildrenFullnames) { + fetchCommentListener.onFetchCommentSuccess(expandedComments, parentId, + moreChildrenFullnames); + } + + @Override + public void onParseCommentFailed() { + fetchCommentListener.onFetchCommentFailed(); + } + }); + } else { + fetchCommentListener.onFetchCommentFailed(); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + fetchCommentListener.onFetchCommentFailed(); + } + }); + } + + public static void fetchMoreComment(Retrofit retrofit, @Nullable String accessToken, + ArrayList allChildren, int startingIndex, + int depth, boolean expandChildren, Locale locale, + FetchMoreCommentListener fetchMoreCommentListener) { + if (allChildren == null) { + return; + } + + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < 100; i++) { + if (allChildren.size() <= startingIndex + i) { + break; + } + stringBuilder.append(allChildren.get(startingIndex + i)).append(","); + } + + if (stringBuilder.length() == 0) { + return; + } + + stringBuilder.deleteCharAt(stringBuilder.length() - 1); + + RedditAPI api = retrofit.create(RedditAPI.class); + Call moreComments; + if (accessToken == null) { + moreComments = api.getInfo(stringBuilder.toString()); + } else { + moreComments = api.getInfoOauth(stringBuilder.toString(), APIUtils.getOAuthHeader(accessToken)); + } + + moreComments.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + ParseComment.parseMoreComment(response.body(), new ArrayList<>(), locale, + depth, expandChildren, new ParseComment.ParseCommentListener() { + @Override + public void onParseCommentSuccess(ArrayList expandedComments, + String parentId, ArrayList moreChildrenFullnames) { + fetchMoreCommentListener.onFetchMoreCommentSuccess(expandedComments, + startingIndex + 100); + } + + @Override + public void onParseCommentFailed() { + fetchMoreCommentListener.onFetchMoreCommentFailed(); + } + }); + } else { + fetchMoreCommentListener.onFetchMoreCommentFailed(); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + fetchMoreCommentListener.onFetchMoreCommentFailed(); + } + }); + } + + public interface FetchCommentListener { + void onFetchCommentSuccess(ArrayList expandedComments, String parentId, ArrayList children); + + void onFetchCommentFailed(); + } + + public interface FetchMoreCommentListener { + void onFetchMoreCommentSuccess(ArrayList expandedComments, int childrenStartingIndex); + + void onFetchMoreCommentFailed(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/ParseComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/ParseComment.java new file mode 100644 index 00000000..fc318e7d --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/ParseComment.java @@ -0,0 +1,322 @@ +package ml.docilealligator.infinityforreddit.Comment; + +import android.os.AsyncTask; +import android.text.Html; + +import androidx.annotation.Nullable; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Locale; + +import ml.docilealligator.infinityforreddit.Utils.JSONUtils; +import ml.docilealligator.infinityforreddit.Utils.Utils; + +import static ml.docilealligator.infinityforreddit.Comment.Comment.VOTE_TYPE_DOWNVOTE; +import static ml.docilealligator.infinityforreddit.Comment.Comment.VOTE_TYPE_NO_VOTE; +import static ml.docilealligator.infinityforreddit.Comment.Comment.VOTE_TYPE_UPVOTE; + +public class ParseComment { + public static void parseComment(String response, ArrayList commentData, Locale locale, + boolean expandChildren, ParseCommentListener parseCommentListener) { + try { + JSONArray childrenArray = new JSONArray(response); + String parentId = childrenArray.getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY) + .getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.NAME_KEY); + childrenArray = childrenArray.getJSONObject(1).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); + + new ParseCommentAsyncTask(childrenArray, commentData, locale, parentId, 0, expandChildren, parseCommentListener).execute(); + } catch (JSONException e) { + e.printStackTrace(); + parseCommentListener.onParseCommentFailed(); + } + } + + static void parseMoreComment(String response, ArrayList commentData, Locale locale, + int depth, boolean expandChildren, ParseCommentListener parseCommentListener) { + try { + JSONArray childrenArray = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); + new ParseCommentAsyncTask(childrenArray, commentData, locale, null, depth, expandChildren, parseCommentListener).execute(); + } catch (JSONException e) { + e.printStackTrace(); + parseCommentListener.onParseCommentFailed(); + } + } + + static void parseSentComment(String response, int depth, Locale locale, + ParseSentCommentListener parseSentCommentListener) { + new ParseSentCommentAsyncTask(response, depth, locale, parseSentCommentListener).execute(); + } + + private static void parseCommentRecursion(JSONArray comments, ArrayList newCommentData, + ArrayList moreChildrenFullnames, int depth, Locale locale) throws JSONException { + int actualCommentLength; + + if (comments.length() == 0) { + return; + } + + JSONObject more = comments.getJSONObject(comments.length() - 1).getJSONObject(JSONUtils.DATA_KEY); + + //Maybe moreChildrenFullnames contain only commentsJSONArray and no more info + if (more.has(JSONUtils.COUNT_KEY)) { + JSONArray childrenArray = more.getJSONArray(JSONUtils.CHILDREN_KEY); + + for (int i = 0; i < childrenArray.length(); i++) { + moreChildrenFullnames.add("t1_" + childrenArray.getString(i)); + } + + actualCommentLength = comments.length() - 1; + } else { + actualCommentLength = comments.length(); + } + + for (int i = 0; i < actualCommentLength; i++) { + JSONObject data = comments.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY); + Comment singleComment = parseSingleComment(data, depth, locale); + + if (data.get(JSONUtils.REPLIES_KEY) instanceof JSONObject) { + JSONArray childrenArray = data.getJSONObject(JSONUtils.REPLIES_KEY) + .getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); + ArrayList children = new ArrayList<>(); + ArrayList nextMoreChildrenFullnames = new ArrayList<>(); + parseCommentRecursion(childrenArray, children, nextMoreChildrenFullnames, singleComment.getDepth(), + locale); + singleComment.addChildren(children); + singleComment.setMoreChildrenFullnames(nextMoreChildrenFullnames); + } + + newCommentData.add(singleComment); + } + } + + private static void expandChildren(ArrayList comments, ArrayList visibleComments, + boolean setExpanded) { + for (Comment c : comments) { + visibleComments.add(c); + if (c.hasReply()) { + if (setExpanded) { + c.setExpanded(true); + } + expandChildren(c.getChildren(), visibleComments, setExpanded); + } + if (c.hasMoreChildrenFullnames() && c.getMoreChildrenFullnames().size() > c.getMoreChildrenStartingIndex()) { + //Add a load more placeholder + Comment placeholder = new Comment(c.getFullName(), c.getDepth() + 1); + visibleComments.add(placeholder); + c.addChild(placeholder, c.getChildren().size()); + } + } + } + + static Comment parseSingleComment(JSONObject singleCommentData, int depth, Locale locale) throws JSONException { + String id = singleCommentData.getString(JSONUtils.ID_KEY); + String fullName = singleCommentData.getString(JSONUtils.NAME_KEY); + String author = singleCommentData.getString(JSONUtils.AUTHOR_KEY); + StringBuilder authorFlairHTMLBuilder = new StringBuilder(); + if (singleCommentData.has(JSONUtils.AUTHOR_FLAIR_RICHTEXT_KEY)) { + JSONArray flairArray = singleCommentData.getJSONArray(JSONUtils.AUTHOR_FLAIR_RICHTEXT_KEY); + for (int i = 0; i < flairArray.length(); i++) { + JSONObject flairObject = flairArray.getJSONObject(i); + String e = flairObject.getString(JSONUtils.E_KEY); + if (e.equals("text")) { + authorFlairHTMLBuilder.append(Html.escapeHtml(flairObject.getString(JSONUtils.T_KEY))); + } else if (e.equals("emoji")) { + authorFlairHTMLBuilder.append(""); + } + } + } + String authorFlair = singleCommentData.isNull(JSONUtils.AUTHOR_FLAIR_TEXT_KEY) ? "" : singleCommentData.getString(JSONUtils.AUTHOR_FLAIR_TEXT_KEY); + String linkAuthor = singleCommentData.has(JSONUtils.LINK_AUTHOR_KEY) ? singleCommentData.getString(JSONUtils.LINK_AUTHOR_KEY) : null; + String linkId = singleCommentData.getString(JSONUtils.LINK_ID_KEY).substring(3); + String subredditName = singleCommentData.getString(JSONUtils.SUBREDDIT_KEY); + String parentId = singleCommentData.getString(JSONUtils.PARENT_ID_KEY); + boolean isSubmitter = singleCommentData.getBoolean(JSONUtils.IS_SUBMITTER_KEY); + String distinguished = singleCommentData.getString(JSONUtils.DISTINGUISHED_KEY); + String commentMarkdown = ""; + if (!singleCommentData.isNull(JSONUtils.BODY_KEY)) { + commentMarkdown = Utils.modifyMarkdown(singleCommentData.getString(JSONUtils.BODY_KEY).trim()); + } + String commentRawText = Utils.trimTrailingWhitespace( + Html.fromHtml(singleCommentData.getString(JSONUtils.BODY_HTML_KEY))).toString(); + String permalink = Html.fromHtml(singleCommentData.getString(JSONUtils.PERMALINK_KEY)).toString(); + StringBuilder awardingsBuilder = new StringBuilder(); + JSONArray awardingsArray = singleCommentData.getJSONArray(JSONUtils.ALL_AWARDINGS_KEY); + for (int i = 0; i < awardingsArray.length(); i++) { + JSONObject award = awardingsArray.getJSONObject(i); + int count = award.getInt(JSONUtils.COUNT_KEY); + JSONArray icons = award.getJSONArray(JSONUtils.RESIZED_ICONS_KEY); + if (icons.length() > 4) { + String iconUrl = icons.getJSONObject(3).getString(JSONUtils.URL_KEY); + awardingsBuilder.append(" ").append("x").append(count).append(" "); + } else if (icons.length() > 0) { + String iconUrl = icons.getJSONObject(icons.length() - 1).getString(JSONUtils.URL_KEY); + awardingsBuilder.append(" ").append("x").append(count).append(" "); + } + } + int score = singleCommentData.getInt(JSONUtils.SCORE_KEY); + int voteType; + if (singleCommentData.isNull(JSONUtils.LIKES_KEY)) { + voteType = VOTE_TYPE_NO_VOTE; + } else { + voteType = singleCommentData.getBoolean(JSONUtils.LIKES_KEY) ? VOTE_TYPE_UPVOTE : VOTE_TYPE_DOWNVOTE; + score -= voteType; + } + long submitTime = singleCommentData.getLong(JSONUtils.CREATED_UTC_KEY) * 1000; + boolean scoreHidden = singleCommentData.getBoolean(JSONUtils.SCORE_HIDDEN_KEY); + boolean saved = singleCommentData.getBoolean(JSONUtils.SAVED_KEY); + + if (singleCommentData.has(JSONUtils.DEPTH_KEY)) { + depth = singleCommentData.getInt(JSONUtils.DEPTH_KEY); + } + + boolean collapsed = singleCommentData.getBoolean(JSONUtils.COLLAPSED_KEY); + boolean hasReply = !(singleCommentData.get(JSONUtils.REPLIES_KEY) instanceof String); + + return new Comment(id, fullName, author, authorFlair, authorFlairHTMLBuilder.toString(), + linkAuthor, submitTime, commentMarkdown, commentRawText, + linkId, subredditName, parentId, score, voteType, isSubmitter, distinguished, + permalink, awardingsBuilder.toString(),depth, collapsed, hasReply, scoreHidden, saved); + } + + @Nullable + private static String parseSentCommentErrorMessage(String response) { + try { + JSONObject responseObject = new JSONObject(response).getJSONObject(JSONUtils.JSON_KEY); + + if (responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() != 0) { + JSONArray error = responseObject.getJSONArray(JSONUtils.ERRORS_KEY) + .getJSONArray(responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() - 1); + if (error.length() != 0) { + String errorString; + if (error.length() >= 2) { + errorString = error.getString(1); + } else { + errorString = error.getString(0); + } + return errorString.substring(0, 1).toUpperCase() + errorString.substring(1); + } else { + return null; + } + } else { + return null; + } + } catch (JSONException e) { + e.printStackTrace(); + } + + return null; + } + + public interface ParseCommentListener { + void onParseCommentSuccess(ArrayList expandedComments, String parentId, + ArrayList moreChildrenFullnames); + + void onParseCommentFailed(); + } + + interface ParseSentCommentListener { + void onParseSentCommentSuccess(Comment comment); + + void onParseSentCommentFailed(@Nullable String errorMessage); + } + + private static class ParseCommentAsyncTask extends AsyncTask { + private JSONArray commentsJSONArray; + private ArrayList comments; + private ArrayList newComments; + private ArrayList expandedNewComments; + private ArrayList moreChildrenFullnames; + private Locale locale; + private String parentId; + private int depth; + private boolean expandChildren; + private ParseCommentListener parseCommentListener; + private boolean parseFailed; + + ParseCommentAsyncTask(JSONArray commentsJSONArray, ArrayList comments, Locale locale, + @Nullable String parentId, int depth, boolean expandChildren, + ParseCommentListener parseCommentListener) { + this.commentsJSONArray = commentsJSONArray; + this.comments = comments; + newComments = new ArrayList<>(); + expandedNewComments = new ArrayList<>(); + moreChildrenFullnames = new ArrayList<>(); + this.locale = locale; + this.parentId = parentId; + this.depth = depth; + this.expandChildren = expandChildren; + parseFailed = false; + this.parseCommentListener = parseCommentListener; + } + + @Override + protected Void doInBackground(Void... voids) { + try { + parseCommentRecursion(commentsJSONArray, newComments, moreChildrenFullnames, depth, locale); + expandChildren(newComments, expandedNewComments, expandChildren); + } catch (JSONException e) { + parseFailed = true; + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + if (!parseFailed) { + if (expandChildren) { + comments.addAll(expandedNewComments); + } else { + comments.addAll(newComments); + } + parseCommentListener.onParseCommentSuccess(comments, parentId, moreChildrenFullnames); + } else { + parseCommentListener.onParseCommentFailed(); + } + } + } + + private static class ParseSentCommentAsyncTask extends AsyncTask { + private String response; + private int depth; + private Locale locale; + private ParseSentCommentListener parseSentCommentListener; + private boolean parseFailed; + private String errorMessage; + private Comment comment; + + ParseSentCommentAsyncTask(String response, int depth, Locale locale, ParseSentCommentListener parseSentCommentListener) { + this.response = response; + this.depth = depth; + this.locale = locale; + this.parseSentCommentListener = parseSentCommentListener; + parseFailed = false; + } + + @Override + protected Void doInBackground(Void... voids) { + try { + JSONObject sentCommentData = new JSONObject(response); + comment = parseSingleComment(sentCommentData, depth, locale); + } catch (JSONException e) { + e.printStackTrace(); + errorMessage = parseSentCommentErrorMessage(response); + parseFailed = true; + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + if (parseFailed) { + parseSentCommentListener.onParseSentCommentFailed(errorMessage); + } else { + parseSentCommentListener.onParseSentCommentSuccess(comment); + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/SendComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/SendComment.java new file mode 100644 index 00000000..1ce8fac5 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Comment/SendComment.java @@ -0,0 +1,64 @@ +package ml.docilealligator.infinityforreddit.Comment; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import ml.docilealligator.infinityforreddit.API.RedditAPI; +import ml.docilealligator.infinityforreddit.Utils.APIUtils; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +public class SendComment { + + 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 = APIUtils.getOAuthHeader(accessToken); + Map params = new HashMap<>(); + params.put(APIUtils.API_TYPE_KEY, "json"); + params.put(APIUtils.RETURN_RTJSON_KEY, "true"); + params.put(APIUtils.TEXT_KEY, commentMarkdown); + params.put(APIUtils.THING_ID_KEY, thingFullname); + api.sendCommentOrReplyToMessage(headers, params); + + Call sendCommentCall = api.sendCommentOrReplyToMessage(headers, params); + sendCommentCall.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + ParseComment.parseSentComment(response.body(), parentDepth, locale, new ParseComment.ParseSentCommentListener() { + @Override + public void onParseSentCommentSuccess(Comment comment) { + sendCommentListener.sendCommentSuccess(comment); + } + + @Override + public void onParseSentCommentFailed(@Nullable String errorMessage) { + sendCommentListener.sendCommentFailed(errorMessage); + } + }); + } else { + sendCommentListener.sendCommentFailed(response.message()); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + sendCommentListener.sendCommentFailed(t.getMessage()); + } + }); + } + + public interface SendCommentListener { + void sendCommentSuccess(Comment comment); + + void sendCommentFailed(String errorMessage); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentData.java deleted file mode 100644 index 0880e19a..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentData.java +++ /dev/null @@ -1,386 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.ArrayList; - -import ml.docilealligator.infinityforreddit.Utils.APIUtils; - -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; - public static final Creator CREATOR = new Creator() { - @Override - public CommentData createFromParcel(Parcel in) { - return new CommentData(in); - } - - @Override - public CommentData[] newArray(int size) { - return new CommentData[size]; - } - }; - private String id; - private String fullName; - private String author; - private String authorFlair; - private String authorFlairHTML; - private String linkAuthor; - private long commentTimeMillis; - private String commentMarkdown; - private String commentRawText; - private String linkId; - private String subredditName; - private String parentId; - private int score; - private int voteType; - private boolean isSubmitter; - private String distinguished; - private String permalink; - private String awards; - private int depth; - private boolean collapsed; - private boolean hasReply; - private boolean scoreHidden; - private boolean saved; - private boolean isExpanded; - private boolean hasExpandedBefore; - private ArrayList children; - private ArrayList moreChildrenFullnames; - private int moreChildrenStartingIndex; - private boolean isPlaceHolder; - private boolean isLoadingMoreChildren; - private boolean loadMoreChildrenFailed; - - public CommentData(String id, String fullName, String author, String authorFlair, - String authorFlairHTML, String linkAuthor, - long commentTimeMillis, String commentMarkdown, String commentRawText, - String linkId, String subredditName, String parentId, int score, - int voteType, boolean isSubmitter, String distinguished, String permalink, - String awards, int depth, boolean collapsed, boolean hasReply, - boolean scoreHidden, boolean saved) { - this.id = id; - this.fullName = fullName; - this.author = author; - this.authorFlair = authorFlair; - this.authorFlairHTML = authorFlairHTML; - this.linkAuthor = linkAuthor; - this.commentTimeMillis = commentTimeMillis; - this.commentMarkdown = commentMarkdown; - this.commentRawText = commentRawText; - this.linkId = linkId; - this.subredditName = subredditName; - this.parentId = parentId; - this.score = score; - this.voteType = voteType; - this.isSubmitter = isSubmitter; - this.distinguished = distinguished; - this.permalink = APIUtils.API_BASE_URI + permalink; - this.awards = awards; - this.depth = depth; - this.collapsed = collapsed; - this.hasReply = hasReply; - this.scoreHidden = scoreHidden; - this.saved = saved; - this.isExpanded = false; - this.hasExpandedBefore = false; - moreChildrenStartingIndex = 0; - isPlaceHolder = false; - } - - public CommentData(String parentFullName, int depth) { - this.fullName = parentFullName; - this.depth = depth; - isPlaceHolder = true; - isLoadingMoreChildren = false; - loadMoreChildrenFailed = false; - } - - protected CommentData(Parcel in) { - id = in.readString(); - fullName = in.readString(); - author = in.readString(); - authorFlair = in.readString(); - authorFlairHTML = in.readString(); - linkAuthor = in.readString(); - commentTimeMillis = in.readLong(); - commentMarkdown = in.readString(); - commentRawText = in.readString(); - linkId = in.readString(); - subredditName = in.readString(); - parentId = in.readString(); - score = in.readInt(); - voteType = in.readInt(); - isSubmitter = in.readByte() != 0; - distinguished = in.readString(); - permalink = in.readString(); - awards = in.readString(); - depth = in.readInt(); - collapsed = in.readByte() != 0; - hasReply = in.readByte() != 0; - scoreHidden = in.readByte() != 0; - isExpanded = in.readByte() != 0; - hasExpandedBefore = in.readByte() != 0; - children = in.readArrayList(CommentData.class.getClassLoader()); - moreChildrenFullnames = in.readArrayList(CommentData.class.getClassLoader()); - moreChildrenStartingIndex = in.readInt(); - isPlaceHolder = in.readByte() != 0; - isLoadingMoreChildren = in.readByte() != 0; - loadMoreChildrenFailed = in.readByte() != 0; - } - - public String getId() { - return id; - } - - public String getFullName() { - return fullName; - } - - public String getAuthor() { - return author; - } - - public void setAuthor(String author) { - this.author = author; - } - - public String getAuthorFlair() { - return authorFlair; - } - - public String getAuthorFlairHTML() { - return authorFlairHTML; - } - - public String getLinkAuthor() { - return linkAuthor; - } - - public long getCommentTimeMillis() { - return commentTimeMillis; - } - - public String getCommentMarkdown() { - return commentMarkdown; - } - - public void setCommentMarkdown(String commentMarkdown) { - this.commentMarkdown = commentMarkdown; - } - - public String getCommentRawText() { - return commentRawText; - } - - public void setCommentRawText(String commentRawText) { - this.commentRawText = commentRawText; - } - - public String getLinkId() { - return linkId; - } - - public String getSubredditName() { - return subredditName; - } - - public String getParentId() { - return parentId; - } - - public void setParentId(String parentId) { - this.parentId = parentId; - } - - public int getScore() { - return score; - } - - public void setScore(int score) { - this.score = score; - } - - public boolean isSubmitter() { - return isSubmitter; - } - - public boolean isModerator() { - return distinguished != null && distinguished.equals("moderator"); - } - - public String getPermalink() { - return permalink; - } - - public String getAwards() { - return awards; - } - - public int getDepth() { - return depth; - } - - public boolean isCollapsed() { - return collapsed; - } - - public boolean hasReply() { - return hasReply; - } - - public void setHasReply(boolean hasReply) { - this.hasReply = hasReply; - } - - public boolean isScoreHidden() { - return scoreHidden; - } - - public boolean isSaved() { - return saved; - } - - public void setSaved(boolean saved) { - this.saved = saved; - } - - public boolean isExpanded() { - return isExpanded; - } - - public void setExpanded(boolean isExpanded) { - this.isExpanded = isExpanded; - if (isExpanded && !hasExpandedBefore) { - hasExpandedBefore = true; - } - } - - public boolean hasExpandedBefore() { - return hasExpandedBefore; - } - - public int getVoteType() { - return voteType; - } - - public void setVoteType(int voteType) { - this.voteType = voteType; - } - - public ArrayList getChildren() { - return children; - } - - public void setChildren(ArrayList children) { - this.children = children; - } - - public void addChildren(ArrayList moreChildren) { - if (children == null || children.size() == 0) { - setChildren(moreChildren); - } else { - if (children.size() > 1 && children.get(children.size() - 1).isPlaceHolder) { - children.addAll(children.size() - 2, moreChildren); - } else { - children.addAll(moreChildren); - } - } - } - - public void addChild(CommentData comment) { - addChild(comment, 0); - } - - public void addChild(CommentData comment, int position) { - if (children == null) { - children = new ArrayList<>(); - } - children.add(position, comment); - } - - public ArrayList getMoreChildrenFullnames() { - return moreChildrenFullnames; - } - - public void setMoreChildrenFullnames(ArrayList moreChildrenFullnames) { - this.moreChildrenFullnames = moreChildrenFullnames; - } - - public boolean hasMoreChildrenFullnames() { - return moreChildrenFullnames != null; - } - - public void removeMoreChildrenFullnames() { - moreChildrenFullnames.clear(); - } - - public int getMoreChildrenStartingIndex() { - return moreChildrenStartingIndex; - } - - public void setMoreChildrenStartingIndex(int moreChildrenStartingIndex) { - this.moreChildrenStartingIndex = moreChildrenStartingIndex; - } - - public boolean isPlaceHolder() { - return isPlaceHolder; - } - - public boolean isLoadingMoreChildren() { - return isLoadingMoreChildren; - } - - public void setLoadingMoreChildren(boolean isLoadingMoreChildren) { - this.isLoadingMoreChildren = isLoadingMoreChildren; - } - - public boolean isLoadMoreChildrenFailed() { - return loadMoreChildrenFailed; - } - - public void setLoadMoreChildrenFailed(boolean loadMoreChildrenFailed) { - this.loadMoreChildrenFailed = loadMoreChildrenFailed; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel parcel, int i) { - parcel.writeString(id); - parcel.writeString(fullName); - parcel.writeString(author); - parcel.writeString(authorFlair); - parcel.writeString(authorFlairHTML); - parcel.writeString(linkAuthor); - parcel.writeLong(commentTimeMillis); - parcel.writeString(commentMarkdown); - parcel.writeString(commentRawText); - parcel.writeString(linkId); - parcel.writeString(subredditName); - parcel.writeString(parentId); - parcel.writeInt(score); - parcel.writeInt(voteType); - parcel.writeByte((byte) (isSubmitter ? 1 : 0)); - parcel.writeString(distinguished); - parcel.writeString(permalink); - parcel.writeString(awards); - parcel.writeInt(depth); - parcel.writeByte((byte) (collapsed ? 1 : 0)); - parcel.writeByte((byte) (hasReply ? 1 : 0)); - parcel.writeByte((byte) (scoreHidden ? 1 : 0)); - parcel.writeByte((byte) (isExpanded ? 1 : 0)); - parcel.writeByte((byte) (hasExpandedBefore ? 1 : 0)); - parcel.writeList(children); - parcel.writeList(moreChildrenFullnames); - parcel.writeInt(moreChildrenStartingIndex); - parcel.writeByte((byte) (isPlaceHolder ? 1 : 0)); - parcel.writeByte((byte) (isLoadingMoreChildren ? 1 : 0)); - parcel.writeByte((byte) (loadMoreChildrenFailed ? 1 : 0)); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSource.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSource.java deleted file mode 100644 index 598579df..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSource.java +++ /dev/null @@ -1,269 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.AsyncTask; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.lifecycle.MutableLiveData; -import androidx.paging.PageKeyedDataSource; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; -import java.util.Locale; - -import ml.docilealligator.infinityforreddit.API.RedditAPI; -import ml.docilealligator.infinityforreddit.Post.PostDataSource; -import ml.docilealligator.infinityforreddit.Utils.JSONUtils; -import ml.docilealligator.infinityforreddit.Utils.APIUtils; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -public class CommentDataSource extends PageKeyedDataSource { - - private Retrofit retrofit; - private Locale locale; - @Nullable - private String accessToken; - private String username; - private SortType sortType; - private boolean areSavedComments; - - private MutableLiveData paginationNetworkStateLiveData; - private MutableLiveData initialLoadStateLiveData; - private MutableLiveData hasPostLiveData; - - private LoadParams params; - private LoadCallback callback; - - CommentDataSource(Retrofit retrofit, Locale locale, @Nullable String accessToken, String username, SortType sortType, - boolean areSavedComments) { - this.retrofit = retrofit; - this.locale = locale; - this.accessToken = accessToken; - this.username = username; - this.sortType = sortType; - this.areSavedComments = areSavedComments; - paginationNetworkStateLiveData = new MutableLiveData<>(); - initialLoadStateLiveData = new MutableLiveData<>(); - hasPostLiveData = new MutableLiveData<>(); - } - - MutableLiveData getPaginationNetworkStateLiveData() { - return paginationNetworkStateLiveData; - } - - MutableLiveData getInitialLoadStateLiveData() { - return initialLoadStateLiveData; - } - - MutableLiveData hasPostLiveData() { - return hasPostLiveData; - } - - void retryLoadingMore() { - loadAfter(params, callback); - } - - @Override - public void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback callback) { - initialLoadStateLiveData.postValue(NetworkState.LOADING); - - RedditAPI api = retrofit.create(RedditAPI.class); - Call commentsCall; - if (areSavedComments) { - if (sortType.getTime() != null) { - commentsCall = api.getUserSavedCommentsOauth(username, PostDataSource.USER_WHERE_SAVED, - null, sortType.getType().value, sortType.getTime().value, - APIUtils.getOAuthHeader(accessToken)); - } else { - commentsCall = api.getUserSavedCommentsOauth(username, PostDataSource.USER_WHERE_SAVED, - null, sortType.getType().value, APIUtils.getOAuthHeader(accessToken)); - } - } else { - if (accessToken == null) { - if (sortType.getTime() != null) { - commentsCall = api.getUserComments(username, null, sortType.getType().value, - sortType.getTime().value); - } else { - commentsCall = api.getUserComments(username, null, sortType.getType().value); - } - } else { - if (sortType.getTime() != null) { - commentsCall = api.getUserCommentsOauth(APIUtils.getOAuthHeader(accessToken), username, - null, sortType.getType().value, sortType.getTime().value); - } else { - commentsCall = api.getUserCommentsOauth(APIUtils.getOAuthHeader(accessToken), username, - null, sortType.getType().value); - } - } - } - commentsCall.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - new ParseCommentAsyncTask(response.body(), locale, new ParseCommentAsyncTask.ParseCommentAsyncTaskListener() { - @Override - public void parseSuccessful(ArrayList comments, String after) { - if (comments.size() == 0) { - hasPostLiveData.postValue(false); - } else { - hasPostLiveData.postValue(true); - } - - if (after == null || after.equals("") || after.equals("null")) { - callback.onResult(comments, null, null); - } else { - callback.onResult(comments, null, after); - } - initialLoadStateLiveData.postValue(NetworkState.LOADED); - } - - @Override - public void parseFailed() { - initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); - } - }).execute(); - } else { - initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); - } - }); - } - - @Override - public void loadBefore(@NonNull LoadParams params, @NonNull LoadCallback callback) { - - } - - @Override - public void loadAfter(@NonNull LoadParams params, @NonNull LoadCallback callback) { - this.params = params; - this.callback = callback; - - paginationNetworkStateLiveData.postValue(NetworkState.LOADING); - - RedditAPI api = retrofit.create(RedditAPI.class); - Call commentsCall; - if (areSavedComments) { - if (sortType.getTime() != null) { - commentsCall = api.getUserSavedCommentsOauth(username, PostDataSource.USER_WHERE_SAVED, params.key, - sortType.getType().value, sortType.getTime().value, APIUtils.getOAuthHeader(accessToken)); - } else { - commentsCall = api.getUserSavedCommentsOauth(username, PostDataSource.USER_WHERE_SAVED, params.key, - sortType.getType().value, APIUtils.getOAuthHeader(accessToken)); - } - } else { - if (accessToken == null) { - if (sortType.getTime() != null) { - commentsCall = api.getUserComments(username, params.key, sortType.getType().value, - sortType.getTime().value); - } else { - commentsCall = api.getUserComments(username, params.key, sortType.getType().value); - } - } else { - if (sortType.getTime() != null) { - commentsCall = api.getUserCommentsOauth(APIUtils.getOAuthHeader(accessToken), - username, params.key, sortType.getType().value, sortType.getTime().value); - } else { - commentsCall = api.getUserCommentsOauth(APIUtils.getOAuthHeader(accessToken), - username, params.key, sortType.getType().value); - } - } - } - commentsCall.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - new ParseCommentAsyncTask(response.body(), locale, new ParseCommentAsyncTask.ParseCommentAsyncTaskListener() { - @Override - public void parseSuccessful(ArrayList comments, String after) { - if (after == null || after.equals("") || after.equals("null")) { - callback.onResult(comments, null); - } else { - callback.onResult(comments, after); - } - paginationNetworkStateLiveData.postValue(NetworkState.LOADED); - } - - @Override - public void parseFailed() { - paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); - } - }).execute(); - } else { - paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error fetching data")); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error fetching data")); - } - }); - } - - private static class ParseCommentAsyncTask extends AsyncTask, ArrayList> { - private String after; - private Locale locale; - private JSONArray commentsJSONArray; - private boolean parseFailed; - private ParseCommentAsyncTaskListener parseCommentAsyncTaskListener; - - ParseCommentAsyncTask(String response, Locale locale, ParseCommentAsyncTaskListener parseCommentAsyncTaskListener) { - this.locale = locale; - this.parseCommentAsyncTaskListener = parseCommentAsyncTaskListener; - try { - JSONObject data = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY); - commentsJSONArray = data.getJSONArray(JSONUtils.CHILDREN_KEY); - after = data.getString(JSONUtils.AFTER_KEY); - parseFailed = false; - } catch (JSONException e) { - parseFailed = true; - e.printStackTrace(); - } - } - - @Override - protected ArrayList doInBackground(Void... voids) { - if (parseFailed) { - return null; - } - - ArrayList comments = new ArrayList<>(); - for (int i = 0; i < commentsJSONArray.length(); i++) { - try { - JSONObject commentJSON = commentsJSONArray.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY); - comments.add(ParseComment.parseSingleComment(commentJSON, 0, locale)); - } catch (JSONException ignored) { - } - } - return comments; - } - - @Override - protected void onPostExecute(ArrayList commentData) { - super.onPostExecute(commentData); - if (commentData != null) { - parseCommentAsyncTaskListener.parseSuccessful(commentData, after); - } else { - parseCommentAsyncTaskListener.parseFailed(); - } - } - - interface ParseCommentAsyncTaskListener { - void parseSuccessful(ArrayList comments, String after); - - void parseFailed(); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSourceFactory.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSourceFactory.java deleted file mode 100644 index 34d24b8a..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSourceFactory.java +++ /dev/null @@ -1,55 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.lifecycle.MutableLiveData; -import androidx.paging.DataSource; - -import java.util.Locale; - -import retrofit2.Retrofit; - -class CommentDataSourceFactory extends DataSource.Factory { - private Retrofit retrofit; - private Locale locale; - private String accessToken; - private String username; - private SortType sortType; - private boolean areSavedComments; - - private CommentDataSource commentDataSource; - private MutableLiveData commentDataSourceLiveData; - - CommentDataSourceFactory(Retrofit retrofit, Locale locale, @Nullable String accessToken, - String username, SortType sortType, - boolean areSavedComments) { - this.retrofit = retrofit; - this.locale = locale; - this.accessToken = accessToken; - this.username = username; - this.sortType = sortType; - this.areSavedComments = areSavedComments; - commentDataSourceLiveData = new MutableLiveData<>(); - } - - @NonNull - @Override - public DataSource create() { - commentDataSource = new CommentDataSource(retrofit, locale, accessToken, username, sortType, - areSavedComments); - commentDataSourceLiveData.postValue(commentDataSource); - return commentDataSource; - } - - public MutableLiveData getCommentDataSourceLiveData() { - return commentDataSourceLiveData; - } - - CommentDataSource getCommentDataSource() { - return commentDataSource; - } - - void changeSortType(SortType sortType) { - this.sortType = sortType; - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentViewModel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentViewModel.java deleted file mode 100644 index 3753ba9f..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentViewModel.java +++ /dev/null @@ -1,103 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import androidx.annotation.NonNull; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.Transformations; -import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; -import androidx.paging.LivePagedListBuilder; -import androidx.paging.PagedList; - -import java.util.Locale; - -import retrofit2.Retrofit; - -public class CommentViewModel extends ViewModel { - private CommentDataSourceFactory commentDataSourceFactory; - private LiveData paginationNetworkState; - private LiveData initialLoadingState; - private LiveData hasCommentLiveData; - private LiveData> comments; - private MutableLiveData sortTypeLiveData; - - public CommentViewModel(Retrofit retrofit, Locale locale, String accessToken, String username, SortType sortType, - boolean areSavedComments) { - commentDataSourceFactory = new CommentDataSourceFactory(retrofit, locale, accessToken, username, sortType, - areSavedComments); - - initialLoadingState = Transformations.switchMap(commentDataSourceFactory.getCommentDataSourceLiveData(), - CommentDataSource::getInitialLoadStateLiveData); - paginationNetworkState = Transformations.switchMap(commentDataSourceFactory.getCommentDataSourceLiveData(), - CommentDataSource::getPaginationNetworkStateLiveData); - hasCommentLiveData = Transformations.switchMap(commentDataSourceFactory.getCommentDataSourceLiveData(), - CommentDataSource::hasPostLiveData); - - sortTypeLiveData = new MutableLiveData<>(); - sortTypeLiveData.postValue(sortType); - - PagedList.Config pagedListConfig = - (new PagedList.Config.Builder()) - .setEnablePlaceholders(false) - .setPageSize(25) - .build(); - - comments = Transformations.switchMap(sortTypeLiveData, sort -> { - commentDataSourceFactory.changeSortType(sortTypeLiveData.getValue()); - return (new LivePagedListBuilder(commentDataSourceFactory, pagedListConfig)).build(); - }); - } - - public LiveData> getComments() { - return comments; - } - - public LiveData getPaginationNetworkState() { - return paginationNetworkState; - } - - public LiveData getInitialLoadingState() { - return initialLoadingState; - } - - public LiveData hasComment() { - return hasCommentLiveData; - } - - public void refresh() { - commentDataSourceFactory.getCommentDataSource().invalidate(); - } - - public void retryLoadingMore() { - commentDataSourceFactory.getCommentDataSource().retryLoadingMore(); - } - - public void changeSortType(SortType sortType) { - sortTypeLiveData.postValue(sortType); - } - - public static class Factory extends ViewModelProvider.NewInstanceFactory { - private Retrofit retrofit; - private Locale locale; - private String accessToken; - private String username; - private SortType sortType; - private boolean areSavedComments; - - public Factory(Retrofit retrofit, Locale locale, String accessToken, String username, - SortType sortType, boolean areSavedComments) { - this.retrofit = retrofit; - this.locale = locale; - this.accessToken = accessToken; - this.username = username; - this.sortType = sortType; - this.areSavedComments = areSavedComments; - } - - @NonNull - @Override - public T create(@NonNull Class modelClass) { - return (T) new CommentViewModel(retrofit, locale, accessToken, username, sortType, areSavedComments); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomTheme.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomTheme.java index 7fbd3359..45c12d6f 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomTheme.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomTheme.java @@ -151,6 +151,22 @@ public class CustomTheme { public int fabIconColor; @ColumnInfo(name = "chip_text_color") public int chipTextColor; + @ColumnInfo(name = "link_color") + public int linkColor; + @ColumnInfo(name = "received_message_text_color") + public int receivedMessageTextColor; + @ColumnInfo(name = "sent_message_text_color") + public int sentMessageTextColor; + @ColumnInfo(name = "received_message_background_color") + public int receivedMessageBackgroundColor; + @ColumnInfo(name = "sent_message_background_color") + public int sentMessageBackgroundColor; + @ColumnInfo(name = "send_message_icon_color") + public int sendMessageIconColor; + @ColumnInfo(name = "fully_collapsed_comment_background_color") + public int fullyCollapsedCommentBackgroundColor; + @ColumnInfo(name = "awarded_comment_background_color") + public int awardedCommentBackgroundColor; @ColumnInfo(name = "is_light_status_bar") public boolean isLightStatusBar; @ColumnInfo(name = "is_light_nav_bar") @@ -190,63 +206,71 @@ public class CustomTheme { customTheme.commentColor = customThemeSettingsItems.get(11).colorValue; customTheme.buttonTextColor = customThemeSettingsItems.get(12).colorValue; customTheme.chipTextColor = customThemeSettingsItems.get(13).colorValue; - customTheme.backgroundColor = customThemeSettingsItems.get(14).colorValue; - customTheme.cardViewBackgroundColor = customThemeSettingsItems.get(15).colorValue; - customTheme.commentBackgroundColor = customThemeSettingsItems.get(16).colorValue; - customTheme.bottomAppBarBackgroundColor = customThemeSettingsItems.get(17).colorValue; - customTheme.primaryIconColor = customThemeSettingsItems.get(18).colorValue; - customTheme.bottomAppBarIconColor = customThemeSettingsItems.get(19).colorValue; - customTheme.postIconAndInfoColor = customThemeSettingsItems.get(20).colorValue; - customTheme.commentIconAndInfoColor = customThemeSettingsItems.get(21).colorValue; - customTheme.fabIconColor = customThemeSettingsItems.get(22).colorValue; - customTheme.toolbarPrimaryTextAndIconColor = customThemeSettingsItems.get(23).colorValue; - customTheme.toolbarSecondaryTextColor = customThemeSettingsItems.get(24).colorValue; - customTheme.circularProgressBarBackground = customThemeSettingsItems.get(25).colorValue; - customTheme.tabLayoutWithExpandedCollapsingToolbarTabBackground = customThemeSettingsItems.get(26).colorValue; - customTheme.tabLayoutWithExpandedCollapsingToolbarTextColor = customThemeSettingsItems.get(27).colorValue; - customTheme.tabLayoutWithExpandedCollapsingToolbarTabIndicator = customThemeSettingsItems.get(28).colorValue; - customTheme.tabLayoutWithCollapsedCollapsingToolbarTabBackground = customThemeSettingsItems.get(29).colorValue; - customTheme.tabLayoutWithCollapsedCollapsingToolbarTextColor = customThemeSettingsItems.get(30).colorValue; - customTheme.tabLayoutWithCollapsedCollapsingToolbarTabIndicator = customThemeSettingsItems.get(31).colorValue; - customTheme.upvoted = customThemeSettingsItems.get(32).colorValue; - customTheme.downvoted = customThemeSettingsItems.get(33).colorValue; - customTheme.postTypeBackgroundColor = customThemeSettingsItems.get(34).colorValue; - customTheme.postTypeTextColor = customThemeSettingsItems.get(35).colorValue; - customTheme.spoilerBackgroundColor = customThemeSettingsItems.get(36).colorValue; - customTheme.spoilerTextColor = customThemeSettingsItems.get(37).colorValue; - customTheme.nsfwBackgroundColor = customThemeSettingsItems.get(38).colorValue; - customTheme.nsfwTextColor = customThemeSettingsItems.get(39).colorValue; - customTheme.flairBackgroundColor = customThemeSettingsItems.get(40).colorValue; - customTheme.flairTextColor = customThemeSettingsItems.get(41).colorValue; - customTheme.awardsBackgroundColor = customThemeSettingsItems.get(42).colorValue; - customTheme.awardsTextColor = customThemeSettingsItems.get(43).colorValue; - customTheme.archivedTint = customThemeSettingsItems.get(44).colorValue; - customTheme.lockedIconTint = customThemeSettingsItems.get(45).colorValue; - customTheme.crosspostIconTint = customThemeSettingsItems.get(46).colorValue; - customTheme.stickiedPostIconTint = customThemeSettingsItems.get(47).colorValue; - customTheme.subscribed = customThemeSettingsItems.get(48).colorValue; - customTheme.unsubscribed = customThemeSettingsItems.get(49).colorValue; - customTheme.username = customThemeSettingsItems.get(50).colorValue; - customTheme.subreddit = customThemeSettingsItems.get(51).colorValue; - customTheme.authorFlairTextColor = customThemeSettingsItems.get(52).colorValue; - customTheme.submitter = customThemeSettingsItems.get(53).colorValue; - customTheme.moderator = customThemeSettingsItems.get(54).colorValue; - customTheme.singleCommentThreadBackgroundColor = customThemeSettingsItems.get(55).colorValue; - customTheme.unreadMessageBackgroundColor = customThemeSettingsItems.get(56).colorValue; - customTheme.dividerColor = customThemeSettingsItems.get(57).colorValue; - customTheme.noPreviewLinkBackgroundColor = customThemeSettingsItems.get(58).colorValue; - customTheme.voteAndReplyUnavailableButtonColor = customThemeSettingsItems.get(59).colorValue; - customTheme.commentVerticalBarColor1 = customThemeSettingsItems.get(60).colorValue; - customTheme.commentVerticalBarColor2 = customThemeSettingsItems.get(61).colorValue; - customTheme.commentVerticalBarColor3 = customThemeSettingsItems.get(62).colorValue; - customTheme.commentVerticalBarColor4 = customThemeSettingsItems.get(63).colorValue; - customTheme.commentVerticalBarColor5 = customThemeSettingsItems.get(64).colorValue; - customTheme.commentVerticalBarColor6 = customThemeSettingsItems.get(65).colorValue; - customTheme.commentVerticalBarColor7 = customThemeSettingsItems.get(66).colorValue; - customTheme.navBarColor = customThemeSettingsItems.get(67).colorValue; - customTheme.isLightStatusBar = customThemeSettingsItems.get(68).isEnabled; - customTheme.isLightNavBar = customThemeSettingsItems.get(69).isEnabled; - customTheme.isChangeStatusBarIconColorAfterToolbarCollapsedInImmersiveInterface = customThemeSettingsItems.get(70).isEnabled; + customTheme.linkColor = customThemeSettingsItems.get(14).colorValue; + customTheme.receivedMessageTextColor = customThemeSettingsItems.get(15).colorValue; + customTheme.sentMessageTextColor = customThemeSettingsItems.get(16).colorValue; + customTheme.backgroundColor = customThemeSettingsItems.get(17).colorValue; + customTheme.cardViewBackgroundColor = customThemeSettingsItems.get(18).colorValue; + customTheme.commentBackgroundColor = customThemeSettingsItems.get(19).colorValue; + customTheme.fullyCollapsedCommentBackgroundColor = customThemeSettingsItems.get(20).colorValue; + customTheme.awardedCommentBackgroundColor = customThemeSettingsItems.get(21).colorValue; + customTheme.receivedMessageBackgroundColor = customThemeSettingsItems.get(22).colorValue; + customTheme.sentMessageBackgroundColor = customThemeSettingsItems.get(23).colorValue; + customTheme.bottomAppBarBackgroundColor = customThemeSettingsItems.get(24).colorValue; + customTheme.primaryIconColor = customThemeSettingsItems.get(25).colorValue; + customTheme.bottomAppBarIconColor = customThemeSettingsItems.get(26).colorValue; + customTheme.postIconAndInfoColor = customThemeSettingsItems.get(27).colorValue; + customTheme.commentIconAndInfoColor = customThemeSettingsItems.get(28).colorValue; + customTheme.fabIconColor = customThemeSettingsItems.get(29).colorValue; + customTheme.sendMessageIconColor = customThemeSettingsItems.get(30).colorValue; + customTheme.toolbarPrimaryTextAndIconColor = customThemeSettingsItems.get(31).colorValue; + customTheme.toolbarSecondaryTextColor = customThemeSettingsItems.get(32).colorValue; + customTheme.circularProgressBarBackground = customThemeSettingsItems.get(33).colorValue; + customTheme.tabLayoutWithExpandedCollapsingToolbarTabBackground = customThemeSettingsItems.get(34).colorValue; + customTheme.tabLayoutWithExpandedCollapsingToolbarTextColor = customThemeSettingsItems.get(35).colorValue; + customTheme.tabLayoutWithExpandedCollapsingToolbarTabIndicator = customThemeSettingsItems.get(36).colorValue; + customTheme.tabLayoutWithCollapsedCollapsingToolbarTabBackground = customThemeSettingsItems.get(37).colorValue; + customTheme.tabLayoutWithCollapsedCollapsingToolbarTextColor = customThemeSettingsItems.get(38).colorValue; + customTheme.tabLayoutWithCollapsedCollapsingToolbarTabIndicator = customThemeSettingsItems.get(39).colorValue; + customTheme.upvoted = customThemeSettingsItems.get(40).colorValue; + customTheme.downvoted = customThemeSettingsItems.get(41).colorValue; + customTheme.postTypeBackgroundColor = customThemeSettingsItems.get(42).colorValue; + customTheme.postTypeTextColor = customThemeSettingsItems.get(43).colorValue; + customTheme.spoilerBackgroundColor = customThemeSettingsItems.get(44).colorValue; + customTheme.spoilerTextColor = customThemeSettingsItems.get(45).colorValue; + customTheme.nsfwBackgroundColor = customThemeSettingsItems.get(46).colorValue; + customTheme.nsfwTextColor = customThemeSettingsItems.get(47).colorValue; + customTheme.flairBackgroundColor = customThemeSettingsItems.get(48).colorValue; + customTheme.flairTextColor = customThemeSettingsItems.get(49).colorValue; + customTheme.awardsBackgroundColor = customThemeSettingsItems.get(50).colorValue; + customTheme.awardsTextColor = customThemeSettingsItems.get(51).colorValue; + customTheme.archivedTint = customThemeSettingsItems.get(52).colorValue; + customTheme.lockedIconTint = customThemeSettingsItems.get(53).colorValue; + customTheme.crosspostIconTint = customThemeSettingsItems.get(54).colorValue; + customTheme.stickiedPostIconTint = customThemeSettingsItems.get(55).colorValue; + customTheme.subscribed = customThemeSettingsItems.get(56).colorValue; + customTheme.unsubscribed = customThemeSettingsItems.get(57).colorValue; + customTheme.username = customThemeSettingsItems.get(58).colorValue; + customTheme.subreddit = customThemeSettingsItems.get(59).colorValue; + customTheme.authorFlairTextColor = customThemeSettingsItems.get(60).colorValue; + customTheme.submitter = customThemeSettingsItems.get(61).colorValue; + customTheme.moderator = customThemeSettingsItems.get(62).colorValue; + customTheme.singleCommentThreadBackgroundColor = customThemeSettingsItems.get(63).colorValue; + customTheme.unreadMessageBackgroundColor = customThemeSettingsItems.get(64).colorValue; + customTheme.dividerColor = customThemeSettingsItems.get(65).colorValue; + customTheme.noPreviewLinkBackgroundColor = customThemeSettingsItems.get(66).colorValue; + customTheme.voteAndReplyUnavailableButtonColor = customThemeSettingsItems.get(67).colorValue; + customTheme.commentVerticalBarColor1 = customThemeSettingsItems.get(68).colorValue; + customTheme.commentVerticalBarColor2 = customThemeSettingsItems.get(69).colorValue; + customTheme.commentVerticalBarColor3 = customThemeSettingsItems.get(70).colorValue; + customTheme.commentVerticalBarColor4 = customThemeSettingsItems.get(71).colorValue; + customTheme.commentVerticalBarColor5 = customThemeSettingsItems.get(72).colorValue; + customTheme.commentVerticalBarColor6 = customThemeSettingsItems.get(73).colorValue; + customTheme.commentVerticalBarColor7 = customThemeSettingsItems.get(74).colorValue; + customTheme.navBarColor = customThemeSettingsItems.get(75).colorValue; + customTheme.isLightStatusBar = customThemeSettingsItems.get(76).isEnabled; + customTheme.isLightNavBar = customThemeSettingsItems.get(77).isEnabled; + customTheme.isChangeStatusBarIconColorAfterToolbarCollapsedInImmersiveInterface = customThemeSettingsItems.get(78).isEnabled; return customTheme; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeSettingsItem.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeSettingsItem.java index b32fcf1a..616446a4 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeSettingsItem.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeSettingsItem.java @@ -110,6 +110,18 @@ public class CustomThemeSettingsItem implements Parcelable { context.getString(R.string.theme_item_chip_text_color), context.getString(R.string.theme_item_chip_text_color_detail), customTheme.chipTextColor)); + customThemeSettingsItems.add(new CustomThemeSettingsItem( + context.getString(R.string.theme_item_link_color), + context.getString(R.string.theme_item_link_color_detail), + customTheme.linkColor)); + customThemeSettingsItems.add(new CustomThemeSettingsItem( + context.getString(R.string.theme_item_received_message_text_color), + context.getString(R.string.theme_item_received_message_text_color_detail), + customTheme.receivedMessageTextColor)); + customThemeSettingsItems.add(new CustomThemeSettingsItem( + context.getString(R.string.theme_item_sent_message_text_color), + context.getString(R.string.theme_item_sent_message_text_color_detail), + customTheme.sentMessageTextColor)); customThemeSettingsItems.add(new CustomThemeSettingsItem( context.getString(R.string.theme_item_background_color), context.getString(R.string.theme_item_background_color_detail), @@ -122,6 +134,22 @@ public class CustomThemeSettingsItem implements Parcelable { context.getString(R.string.theme_item_comment_background_color), context.getString(R.string.theme_item_comment_background_color_detail), customTheme.commentBackgroundColor)); + customThemeSettingsItems.add(new CustomThemeSettingsItem( + context.getString(R.string.theme_item_fully_collapsed_comment_background_color), + context.getString(R.string.theme_item_fully_collapsed_comment_background_color_detail), + customTheme.fullyCollapsedCommentBackgroundColor)); + customThemeSettingsItems.add(new CustomThemeSettingsItem( + context.getString(R.string.theme_item_awarded_comment_background_color), + context.getString(R.string.theme_item_awarded_comment_background_color_detail), + customTheme.awardedCommentBackgroundColor)); + customThemeSettingsItems.add(new CustomThemeSettingsItem( + context.getString(R.string.theme_item_received_message_background_color), + context.getString(R.string.theme_item_received_message_background_color_detail), + customTheme.receivedMessageBackgroundColor)); + customThemeSettingsItems.add(new CustomThemeSettingsItem( + context.getString(R.string.theme_item_sent_message_background_color), + context.getString(R.string.theme_item_sent_message_background_color_detail), + customTheme.sentMessageBackgroundColor)); customThemeSettingsItems.add(new CustomThemeSettingsItem( context.getString(R.string.theme_item_bottom_app_bar_background_color), context.getString(R.string.theme_item_bottom_app_bar_background_color_detail), @@ -146,6 +174,10 @@ public class CustomThemeSettingsItem implements Parcelable { context.getString(R.string.theme_item_fab_icon_color), context.getString(R.string.theme_item_fab_icon_color_detail), customTheme.fabIconColor)); + customThemeSettingsItems.add(new CustomThemeSettingsItem( + context.getString(R.string.theme_item_send_message_icon_color), + context.getString(R.string.theme_item_send_message_icon_color_detail), + customTheme.sendMessageIconColor)); customThemeSettingsItems.add(new CustomThemeSettingsItem( context.getString(R.string.theme_item_toolbar_primary_text_and_icon_color), context.getString(R.string.theme_item_toolbar_primary_text_and_icon_color_detail), diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeWrapper.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeWrapper.java index aef072c9..7f137eed 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeWrapper.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CustomTheme/CustomThemeWrapper.java @@ -372,6 +372,46 @@ public class CustomThemeWrapper { getDefaultColor("#FFFFFF", "#FFFFFF", "#FFFFFF")); } + public int getLinkColor() { + return getThemeSharedPreferences().getInt(CustomThemeSharedPreferencesUtils.LINK_COLOR, + getDefaultColor("#FF4081", "#FF4081", "#FF4081")); + } + + public int getReceivedMessageTextColor() { + return getThemeSharedPreferences().getInt(CustomThemeSharedPreferencesUtils.RECEIVED_MESSAGE_TEXT_COLOR, + getDefaultColor("#FFFFFF", "#FFFFFF", "#FFFFFF")); + } + + public int getSentMessageTextColor() { + return getThemeSharedPreferences().getInt(CustomThemeSharedPreferencesUtils.SENT_MESSAGE_TEXT_COLOR, + getDefaultColor("#FFFFFF", "#FFFFFF", "#FFFFFF")); + } + + public int getReceivedMessageBackgroundColor() { + return getThemeSharedPreferences().getInt(CustomThemeSharedPreferencesUtils.RECEIVED_MESSAGE_BACKROUND_COLOR, + getDefaultColor("#4185F4", "#4185F4", "#4185F4")); + } + + public int getSentMessageBackgroundColor() { + return getThemeSharedPreferences().getInt(CustomThemeSharedPreferencesUtils.SENT_MESSAGE_BACKGROUND_COLOR, + getDefaultColor("#31BF7D", "#31BF7D", "#31BF7D")); + } + + public int getSendMessageIconColor() { + return getThemeSharedPreferences().getInt(CustomThemeSharedPreferencesUtils.SEND_MESSAGE_ICON_COLOR, + getDefaultColor("#4185F4", "#4185F4", "#4185F4")); + } + + public int getFullyCollapsedCommentBackgroundColor() { + return getThemeSharedPreferences().getInt(CustomThemeSharedPreferencesUtils.FULLY_COLLAPSED_COMMENT_BACKGROUND_COLOR, + getDefaultColor("#4185F4", "#4185F4", "#4185F4")); + } + + public int getAwardedCommentBackgroundColor() { + return getThemeSharedPreferences().getInt(CustomThemeSharedPreferencesUtils.AWARDED_COMMENT_BACKGROUND_COLOR, + getDefaultColor("#EEAB02", "#EEAB02", "#EEAB02")); + } + public int getNavBarColor() { return getThemeSharedPreferences().getInt(CustomThemeSharedPreferencesUtils.NAV_BAR_COLOR, getDefaultColor("#FFFFFF", "#121212", "#000000")); @@ -503,6 +543,14 @@ public class CustomThemeWrapper { customTheme.commentVerticalBarColor7 = Color.parseColor("#EE4602"); customTheme.fabIconColor = Color.parseColor("#FFFFFF"); customTheme.chipTextColor = Color.parseColor("#FFFFFF"); + customTheme.linkColor = Color.parseColor("#FF4081"); + customTheme.receivedMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.sentMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.receivedMessageBackgroundColor = Color.parseColor("#4185F4"); + customTheme.sentMessageBackgroundColor = Color.parseColor("#31BF7D"); + customTheme.sendMessageIconColor = Color.parseColor("#4185F4"); + customTheme.fullyCollapsedCommentBackgroundColor = Color.parseColor("#4185F4"); + customTheme.awardedCommentBackgroundColor = Color.parseColor("#EEAB02"); customTheme.navBarColor = Color.parseColor("#FFFFFF"); customTheme.isLightStatusBar = false; customTheme.isLightNavBar = true; @@ -580,6 +628,14 @@ public class CustomThemeWrapper { customTheme.commentVerticalBarColor7 = Color.parseColor("#EE4602"); customTheme.fabIconColor = Color.parseColor("#FFFFFF"); customTheme.chipTextColor = Color.parseColor("#FFFFFF"); + customTheme.linkColor = Color.parseColor("#FF4081"); + customTheme.receivedMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.sentMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.receivedMessageBackgroundColor = Color.parseColor("#4185F4"); + customTheme.sentMessageBackgroundColor = Color.parseColor("#31BF7D"); + customTheme.sendMessageIconColor = Color.parseColor("#4185F4"); + customTheme.fullyCollapsedCommentBackgroundColor = Color.parseColor("#4185F4"); + customTheme.awardedCommentBackgroundColor = Color.parseColor("#EEAB02"); customTheme.navBarColor = Color.parseColor("#121212"); customTheme.isLightStatusBar = false; customTheme.isLightNavBar = false; @@ -657,6 +713,14 @@ public class CustomThemeWrapper { customTheme.commentVerticalBarColor7 = Color.parseColor("#EE4602"); customTheme.fabIconColor = Color.parseColor("#FFFFFF"); customTheme.chipTextColor = Color.parseColor("#FFFFFF"); + customTheme.linkColor = Color.parseColor("#FF4081"); + customTheme.receivedMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.sentMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.receivedMessageBackgroundColor = Color.parseColor("#4185F4"); + customTheme.sentMessageBackgroundColor = Color.parseColor("#31BF7D"); + customTheme.sendMessageIconColor = Color.parseColor("#4185F4"); + customTheme.fullyCollapsedCommentBackgroundColor = Color.parseColor("#4185F4"); + customTheme.awardedCommentBackgroundColor = Color.parseColor("#EEAB02"); customTheme.navBarColor = Color.parseColor("#000000"); customTheme.isLightStatusBar = false; customTheme.isLightNavBar = false; @@ -734,6 +798,14 @@ public class CustomThemeWrapper { customTheme.commentVerticalBarColor7 = Color.parseColor("#EE4602"); customTheme.fabIconColor = Color.parseColor("#000000"); customTheme.chipTextColor = Color.parseColor("#FFFFFF"); + customTheme.linkColor = Color.parseColor("#FF4081"); + customTheme.receivedMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.sentMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.receivedMessageBackgroundColor = Color.parseColor("#4185F4"); + customTheme.sentMessageBackgroundColor = Color.parseColor("#31BF7D"); + customTheme.sendMessageIconColor = Color.parseColor("#4185F4"); + customTheme.fullyCollapsedCommentBackgroundColor = Color.parseColor("#4185F4"); + customTheme.awardedCommentBackgroundColor = Color.parseColor("#EEAB02"); customTheme.navBarColor = Color.parseColor("#FFFFFF"); customTheme.isLightStatusBar = true; customTheme.isLightNavBar = true; @@ -811,6 +883,14 @@ public class CustomThemeWrapper { customTheme.commentVerticalBarColor7 = Color.parseColor("#EE4602"); customTheme.fabIconColor = Color.parseColor("#FFFFFF"); customTheme.chipTextColor = Color.parseColor("#FFFFFF"); + customTheme.linkColor = Color.parseColor("#FF4081"); + customTheme.receivedMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.sentMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.receivedMessageBackgroundColor = Color.parseColor("#4185F4"); + customTheme.sentMessageBackgroundColor = Color.parseColor("#31BF7D"); + customTheme.sendMessageIconColor = Color.parseColor("#4185F4"); + customTheme.fullyCollapsedCommentBackgroundColor = Color.parseColor("#4185F4"); + customTheme.awardedCommentBackgroundColor = Color.parseColor("#EEAB02"); customTheme.navBarColor = Color.parseColor("#121212"); customTheme.isLightStatusBar = false; customTheme.isLightNavBar = false; @@ -888,6 +968,14 @@ public class CustomThemeWrapper { customTheme.commentVerticalBarColor7 = Color.parseColor("#EE4602"); customTheme.fabIconColor = Color.parseColor("#FFFFFF"); customTheme.chipTextColor = Color.parseColor("#FFFFFF"); + customTheme.linkColor = Color.parseColor("#FF4081"); + customTheme.receivedMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.sentMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.receivedMessageBackgroundColor = Color.parseColor("#4185F4"); + customTheme.sentMessageBackgroundColor = Color.parseColor("#31BF7D"); + customTheme.sendMessageIconColor = Color.parseColor("#4185F4"); + customTheme.fullyCollapsedCommentBackgroundColor = Color.parseColor("#4185F4"); + customTheme.awardedCommentBackgroundColor = Color.parseColor("#EEAB02"); customTheme.navBarColor = Color.parseColor("#000000"); customTheme.isLightStatusBar = false; customTheme.isLightNavBar = false; @@ -965,6 +1053,14 @@ public class CustomThemeWrapper { customTheme.commentVerticalBarColor7 = Color.parseColor("#EE4602"); customTheme.fabIconColor = Color.parseColor("#FFFFFF"); customTheme.chipTextColor = Color.parseColor("#FFFFFF"); + customTheme.linkColor = Color.parseColor("#FF4081"); + customTheme.receivedMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.sentMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.receivedMessageBackgroundColor = Color.parseColor("#4185F4"); + customTheme.sentMessageBackgroundColor = Color.parseColor("#31BF7D"); + customTheme.sendMessageIconColor = Color.parseColor("#4185F4"); + customTheme.fullyCollapsedCommentBackgroundColor = Color.parseColor("#4185F4"); + customTheme.awardedCommentBackgroundColor = Color.parseColor("#EEAB02"); customTheme.navBarColor = Color.parseColor("#FFFFFF"); customTheme.isLightStatusBar = false; customTheme.isLightNavBar = true; @@ -1042,6 +1138,14 @@ public class CustomThemeWrapper { customTheme.commentVerticalBarColor7 = Color.parseColor("#EE4602"); customTheme.fabIconColor = Color.parseColor("#FFFFFF"); customTheme.chipTextColor = Color.parseColor("#FFFFFF"); + customTheme.linkColor = Color.parseColor("#FF4081"); + customTheme.receivedMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.sentMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.receivedMessageBackgroundColor = Color.parseColor("#4185F4"); + customTheme.sentMessageBackgroundColor = Color.parseColor("#31BF7D"); + customTheme.sendMessageIconColor = Color.parseColor("#4185F4"); + customTheme.fullyCollapsedCommentBackgroundColor = Color.parseColor("#4185F4"); + customTheme.awardedCommentBackgroundColor = Color.parseColor("#EEAB02"); customTheme.navBarColor = Color.parseColor("#121212"); customTheme.isLightStatusBar = false; customTheme.isLightNavBar = false; @@ -1119,6 +1223,14 @@ public class CustomThemeWrapper { customTheme.commentVerticalBarColor7 = Color.parseColor("#EE4602"); customTheme.fabIconColor = Color.parseColor("#FFFFFF"); customTheme.chipTextColor = Color.parseColor("#FFFFFF"); + customTheme.linkColor = Color.parseColor("#FF4081"); + customTheme.receivedMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.sentMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.receivedMessageBackgroundColor = Color.parseColor("#4185F4"); + customTheme.sentMessageBackgroundColor = Color.parseColor("#31BF7D"); + customTheme.sendMessageIconColor = Color.parseColor("#4185F4"); + customTheme.fullyCollapsedCommentBackgroundColor = Color.parseColor("#4185F4"); + customTheme.awardedCommentBackgroundColor = Color.parseColor("#EEAB02"); customTheme.navBarColor = Color.parseColor("#000000"); customTheme.isLightStatusBar = false; customTheme.isLightNavBar = false; @@ -1196,6 +1308,14 @@ public class CustomThemeWrapper { customTheme.commentVerticalBarColor7 = Color.parseColor("#F1FA8C"); customTheme.fabIconColor = Color.parseColor("#FFFFFF"); customTheme.chipTextColor = Color.parseColor("#FFFFFF"); + customTheme.linkColor = Color.parseColor("#FF4081"); + customTheme.receivedMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.sentMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.receivedMessageBackgroundColor = Color.parseColor("#4185F4"); + customTheme.sentMessageBackgroundColor = Color.parseColor("#31BF7D"); + customTheme.sendMessageIconColor = Color.parseColor("#4185F4"); + customTheme.fullyCollapsedCommentBackgroundColor = Color.parseColor("#4185F4"); + customTheme.awardedCommentBackgroundColor = Color.parseColor("#EEAB02"); customTheme.navBarColor = Color.parseColor("#393A59"); customTheme.isLightStatusBar = false; customTheme.isLightNavBar = false; @@ -1273,6 +1393,14 @@ public class CustomThemeWrapper { customTheme.commentVerticalBarColor7 = Color.parseColor("#EE4602"); customTheme.fabIconColor = Color.parseColor("#000000"); customTheme.chipTextColor = Color.parseColor("#FFFFFF"); + customTheme.linkColor = Color.parseColor("#FF4081"); + customTheme.receivedMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.sentMessageTextColor = Color.parseColor("#FFFFFF"); + customTheme.receivedMessageBackgroundColor = Color.parseColor("#4185F4"); + customTheme.sentMessageBackgroundColor = Color.parseColor("#31BF7D"); + customTheme.sendMessageIconColor = Color.parseColor("#4185F4"); + customTheme.fullyCollapsedCommentBackgroundColor = Color.parseColor("#4185F4"); + customTheme.awardedCommentBackgroundColor = Color.parseColor("#EEAB02"); customTheme.navBarColor = Color.parseColor("#D48AE0"); customTheme.isLightStatusBar = true; customTheme.isLightNavBar = true; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Event/RepliedToPrivateMessageEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/RepliedToPrivateMessageEvent.java index 4e89b4ec..59d82f3c 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Event/RepliedToPrivateMessageEvent.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/RepliedToPrivateMessageEvent.java @@ -1,6 +1,6 @@ package ml.docilealligator.infinityforreddit.Event; -import ml.docilealligator.infinityforreddit.Message; +import ml.docilealligator.infinityforreddit.Message.Message; public class RepliedToPrivateMessageEvent { public Message newReply; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java deleted file mode 100644 index b6b16c1b..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java +++ /dev/null @@ -1,138 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import java.util.ArrayList; -import java.util.Locale; - -import ml.docilealligator.infinityforreddit.API.RedditAPI; -import ml.docilealligator.infinityforreddit.Utils.APIUtils; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -public class FetchComment { - public static void fetchComments(Retrofit retrofit, @Nullable String accessToken, String article, - String commentId, String sortType, boolean expandChildren, - Locale locale, FetchCommentListener fetchCommentListener) { - RedditAPI api = retrofit.create(RedditAPI.class); - Call comments; - if (accessToken == null) { - if (commentId == null) { - comments = api.getPostAndCommentsById(article, sortType); - } else { - comments = api.getPostAndCommentsSingleThreadById(article, commentId, sortType); - } - } else { - if (commentId == null) { - comments = api.getPostAndCommentsByIdOauth(article, sortType, APIUtils.getOAuthHeader(accessToken)); - } else { - comments = api.getPostAndCommentsSingleThreadByIdOauth(article, commentId, sortType, - APIUtils.getOAuthHeader(accessToken)); - } - } - - comments.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - ParseComment.parseComment(response.body(), new ArrayList<>(), - locale, expandChildren, new ParseComment.ParseCommentListener() { - @Override - public void onParseCommentSuccess(ArrayList expandedComments, - String parentId, ArrayList moreChildrenFullnames) { - fetchCommentListener.onFetchCommentSuccess(expandedComments, parentId, - moreChildrenFullnames); - } - - @Override - public void onParseCommentFailed() { - fetchCommentListener.onFetchCommentFailed(); - } - }); - } else { - fetchCommentListener.onFetchCommentFailed(); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - fetchCommentListener.onFetchCommentFailed(); - } - }); - } - - public static void fetchMoreComment(Retrofit retrofit, @Nullable String accessToken, - ArrayList allChildren, int startingIndex, - int depth, boolean expandChildren, Locale locale, - FetchMoreCommentListener fetchMoreCommentListener) { - if (allChildren == null) { - return; - } - - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < 100; i++) { - if (allChildren.size() <= startingIndex + i) { - break; - } - stringBuilder.append(allChildren.get(startingIndex + i)).append(","); - } - - if (stringBuilder.length() == 0) { - return; - } - - stringBuilder.deleteCharAt(stringBuilder.length() - 1); - - RedditAPI api = retrofit.create(RedditAPI.class); - Call moreComments; - if (accessToken == null) { - moreComments = api.getInfo(stringBuilder.toString()); - } else { - moreComments = api.getInfoOauth(stringBuilder.toString(), APIUtils.getOAuthHeader(accessToken)); - } - - moreComments.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - ParseComment.parseMoreComment(response.body(), new ArrayList<>(), locale, - depth, expandChildren, new ParseComment.ParseCommentListener() { - @Override - public void onParseCommentSuccess(ArrayList expandedComments, - String parentId, ArrayList moreChildrenFullnames) { - fetchMoreCommentListener.onFetchMoreCommentSuccess(expandedComments, - startingIndex + 100); - } - - @Override - public void onParseCommentFailed() { - fetchMoreCommentListener.onFetchMoreCommentFailed(); - } - }); - } else { - fetchMoreCommentListener.onFetchMoreCommentFailed(); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - fetchMoreCommentListener.onFetchMoreCommentFailed(); - } - }); - } - - public interface FetchCommentListener { - void onFetchCommentSuccess(ArrayList expandedComments, String parentId, ArrayList children); - - void onFetchCommentFailed(); - } - - public interface FetchMoreCommentListener { - void onFetchMoreCommentSuccess(ArrayList expandedComments, int childrenStartingIndex); - - void onFetchMoreCommentFailed(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchMessages.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchMessages.java deleted file mode 100644 index a1a6552c..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchMessages.java +++ /dev/null @@ -1,53 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import java.util.ArrayList; -import java.util.Locale; - -import ml.docilealligator.infinityforreddit.API.RedditAPI; -import ml.docilealligator.infinityforreddit.Utils.APIUtils; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -public class FetchMessages { - - 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"; - public static final String WHERE_MESSAGES = "messages"; - public static final String WHERE_MESSAGES_DETAIL = "messages_detail"; - public static final int MESSAGE_TYPE_INBOX = 0; - public static final int MESSAGE_TYPE_PRIVATE_MESSAGE = 1; - public static final int MESSAGE_TYPE_NOTIFICATION = 2; - - static void fetchInbox(Retrofit oauthRetrofit, Locale locale, String accessToken, String where, - String after, int messageType, FetchMessagesListener fetchMessagesListener) { - oauthRetrofit.create(RedditAPI.class).getMessages(APIUtils.getOAuthHeader(accessToken), where, after) - .enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - ParseMessage.parseMessage(response.body(), locale, messageType, fetchMessagesListener::fetchSuccess); - } else { - fetchMessagesListener.fetchFailed(); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - fetchMessagesListener.fetchFailed(); - } - }); - } - - interface FetchMessagesListener { - void fetchSuccess(ArrayList messages, @Nullable String after); - - void fetchFailed(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchRemovedComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchRemovedComment.java index d012342e..658ddc88 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchRemovedComment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchRemovedComment.java @@ -8,6 +8,7 @@ import org.json.JSONException; import org.json.JSONObject; import ml.docilealligator.infinityforreddit.API.PushshiftAPI; +import ml.docilealligator.infinityforreddit.Comment.Comment; import ml.docilealligator.infinityforreddit.Utils.JSONUtils; import ml.docilealligator.infinityforreddit.Utils.Utils; import retrofit2.Call; @@ -17,7 +18,7 @@ import retrofit2.Retrofit; public class FetchRemovedComment { - public static void fetchRemovedComment(Retrofit retrofit, CommentData comment, FetchRemovedCommentListener listener) { + public static void fetchRemovedComment(Retrofit retrofit, Comment comment, FetchRemovedCommentListener listener) { retrofit.create(PushshiftAPI.class).getRemovedComment(comment.getId()) .enqueue(new Callback() { @Override @@ -37,7 +38,7 @@ public class FetchRemovedComment { }); } - private static CommentData parseRemovedComment(JSONObject result, CommentData comment) throws JSONException { + private static Comment parseRemovedComment(JSONObject result, Comment comment) throws JSONException { String id = result.getString(JSONUtils.ID_KEY); String author = result.getString(JSONUtils.AUTHOR_KEY); String body = Utils.modifyMarkdown(result.optString(JSONUtils.BODY_KEY).trim()); @@ -56,7 +57,7 @@ public class FetchRemovedComment { } public interface FetchRemovedCommentListener { - void fetchSuccess(CommentData comment); + void fetchSuccess(Comment comment); void fetchFailed(); } @@ -65,9 +66,9 @@ public class FetchRemovedComment { private String responseBody; private FetchRemovedCommentListener listener; - CommentData comment; + Comment comment; - public ParseCommentAsyncTask(String responseBody, CommentData comment, FetchRemovedCommentListener listener) { + public ParseCommentAsyncTask(String responseBody, Comment comment, FetchRemovedCommentListener listener) { this.responseBody = responseBody; this.comment = comment; this.listener = listener; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/CommentsListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/CommentsListingFragment.java index 015d56eb..6a866fef 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/CommentsListingFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/CommentsListingFragment.java @@ -33,7 +33,7 @@ import butterknife.ButterKnife; import ml.docilealligator.infinityforreddit.Activity.BaseActivity; import ml.docilealligator.infinityforreddit.Adapter.CommentsListingRecyclerViewAdapter; import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; -import ml.docilealligator.infinityforreddit.CommentViewModel; +import ml.docilealligator.infinityforreddit.Comment.CommentViewModel; import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.FragmentCommunicator; import ml.docilealligator.infinityforreddit.Infinity; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/InboxFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/InboxFragment.java index 9129bec2..56f4c2a0 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/InboxFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/InboxFragment.java @@ -33,10 +33,10 @@ import ml.docilealligator.infinityforreddit.Activity.BaseActivity; import ml.docilealligator.infinityforreddit.Adapter.MessageRecyclerViewAdapter; import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.Event.RepliedToPrivateMessageEvent; -import ml.docilealligator.infinityforreddit.FetchMessages; +import ml.docilealligator.infinityforreddit.Message.FetchMessage; import ml.docilealligator.infinityforreddit.FragmentCommunicator; import ml.docilealligator.infinityforreddit.Infinity; -import ml.docilealligator.infinityforreddit.MessageViewModel; +import ml.docilealligator.infinityforreddit.Message.MessageViewModel; import ml.docilealligator.infinityforreddit.NetworkState; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; @@ -102,7 +102,7 @@ public class InboxFragment extends Fragment implements FragmentCommunicator { mRecyclerView.setPadding(0, 0, 0, mActivity.getNavBarHeight()); } - mWhere = arguments.getString(EXTRA_MESSAGE_WHERE, FetchMessages.WHERE_INBOX); + mWhere = arguments.getString(EXTRA_MESSAGE_WHERE, FetchMessage.WHERE_INBOX); mAdapter = new MessageRecyclerViewAdapter(mActivity, mOauthRetrofit, mCustomThemeWrapper, mAccessToken, mWhere, () -> mMessageViewModel.retryLoadingMore()); mLinearLayoutManager = new LinearLayoutManager(mActivity); @@ -190,7 +190,7 @@ public class InboxFragment extends Fragment implements FragmentCommunicator { @Subscribe public void onRepliedToPrivateMessageEvent(RepliedToPrivateMessageEvent repliedToPrivateMessageEvent) { - if (mAdapter != null && mWhere.equals(FetchMessages.WHERE_MESSAGES)) { + if (mAdapter != null && mWhere.equals(FetchMessage.WHERE_MESSAGES)) { mAdapter.updateMessageReply(repliedToPrivateMessageEvent.newReply, repliedToPrivateMessageEvent.messagePosition); } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SidebarFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SidebarFragment.java index 9d9aa9b7..6e070c5e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SidebarFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/SidebarFragment.java @@ -31,6 +31,7 @@ import butterknife.ButterKnife; import io.noties.markwon.AbstractMarkwonPlugin; import io.noties.markwon.Markwon; import io.noties.markwon.MarkwonConfiguration; +import io.noties.markwon.core.MarkwonTheme; import io.noties.markwon.ext.strikethrough.StrikethroughPlugin; import io.noties.markwon.linkify.LinkifyPlugin; import io.noties.markwon.recycler.MarkwonAdapter; @@ -101,6 +102,11 @@ public class SidebarFragment extends Fragment { textView.setTextColor(markdownColor); } + @Override + public void configureTheme(@NonNull MarkwonTheme.Builder builder) { + builder.linkColor(mCustomThemeWrapper.getLinkColor()); + } + @Override public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { builder.linkResolver((view, link) -> { @@ -113,6 +119,7 @@ public class SidebarFragment extends Fragment { } startActivity(intent); }).urlProcessor(new UrlProcessorRelativeToAbsolute("https://www.reddit.com")); + } }) .usePlugin(StrikethroughPlugin.create()) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Message.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Message.java deleted file mode 100644 index 9f3131e0..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Message.java +++ /dev/null @@ -1,213 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.ArrayList; - -public class Message implements Parcelable { - static final String TYPE_COMMENT = "t1"; - static final String TYPE_ACCOUNT = "t2"; - static final String TYPE_LINK = "t3"; - static final String TYPE_MESSAGE = "t4"; - static final String TYPE_SUBREDDIT = "t5"; - static final String TYPE_AWARD = "t6"; - - private String kind; - private String subredditName; - private String subredditNamePrefixed; - private String id; - private String fullname; - private String subject; - private String author; - private String parentFullName; - private String title; - private String body; - private String context; - private String distinguished; - private String formattedTime; - private boolean wasComment; - private boolean isNew; - private int score; - private int nComments; - private long timeUTC; - private ArrayList replies; - - Message(String kind, String subredditName, String subredditNamePrefixed, String id, String fullname, - String subject, String author, String parentFullName, String title, String body, String context, - String distinguished, String formattedTime, boolean wasComment, boolean isNew, int score, - int nComments, long timeUTC) { - this.kind = kind; - this.subredditName = subredditName; - this.subredditNamePrefixed = subredditNamePrefixed; - this.id = id; - this.fullname = fullname; - this.subject = subject; - this.author = author; - this.parentFullName = parentFullName; - this.title = title; - this.body = body; - this.context = context; - this.distinguished = distinguished; - this.formattedTime = formattedTime; - this.wasComment = wasComment; - this.isNew = isNew; - this.score = score; - this.nComments = nComments; - this.timeUTC = timeUTC; - } - - - protected Message(Parcel in) { - kind = in.readString(); - subredditName = in.readString(); - subredditNamePrefixed = in.readString(); - id = in.readString(); - fullname = in.readString(); - subject = in.readString(); - author = in.readString(); - parentFullName = in.readString(); - title = in.readString(); - body = in.readString(); - context = in.readString(); - distinguished = in.readString(); - formattedTime = in.readString(); - wasComment = in.readByte() != 0; - isNew = in.readByte() != 0; - score = in.readInt(); - nComments = in.readInt(); - timeUTC = in.readLong(); - replies = in.createTypedArrayList(Message.CREATOR); - } - - public static final Creator CREATOR = new Creator() { - @Override - public Message createFromParcel(Parcel in) { - return new Message(in); - } - - @Override - public Message[] newArray(int size) { - return new Message[size]; - } - }; - - public String getKind() { - return kind; - } - - public String getSubredditName() { - return subredditName; - } - - public String getSubredditNamePrefixed() { - return subredditNamePrefixed; - } - - public String getId() { - return id; - } - - public String getFullname() { - return fullname; - } - - public String getSubject() { - return subject; - } - - public String getAuthor() { - return author; - } - - public String getParentFullName() { - return parentFullName; - } - - public String getTitle() { - return title; - } - - public String getBody() { - return body; - } - - public String getContext() { - return context; - } - - public String getDistinguished() { - return distinguished; - } - - public String getFormattedTime() { - return formattedTime; - } - - public boolean wasComment() { - return wasComment; - } - - public boolean isNew() { - return isNew; - } - - public void setNew(boolean isNew) { - this.isNew = isNew; - } - - public int getScore() { - return score; - } - - public int getnComments() { - return nComments; - } - - public long getTimeUTC() { - return timeUTC; - } - - public ArrayList getReplies() { - return replies; - } - - public void setReplies(ArrayList replies) { - this.replies = replies; - } - - public void addReply(Message reply) { - if (replies == null) { - replies = new ArrayList<>(); - } - replies.add(reply); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel parcel, int i) { - parcel.writeString(kind); - parcel.writeString(subredditName); - parcel.writeString(subredditNamePrefixed); - parcel.writeString(id); - parcel.writeString(fullname); - parcel.writeString(subject); - parcel.writeString(author); - parcel.writeString(parentFullName); - parcel.writeString(title); - parcel.writeString(body); - parcel.writeString(context); - parcel.writeString(distinguished); - parcel.writeString(formattedTime); - parcel.writeByte((byte) (wasComment ? 1 : 0)); - parcel.writeByte((byte) (isNew ? 1 : 0)); - parcel.writeInt(score); - parcel.writeInt(nComments); - parcel.writeLong(timeUTC); - parcel.writeTypedList(replies); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Message/FetchMessage.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/FetchMessage.java new file mode 100644 index 00000000..1322d7c0 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/FetchMessage.java @@ -0,0 +1,53 @@ +package ml.docilealligator.infinityforreddit.Message; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.ArrayList; +import java.util.Locale; + +import ml.docilealligator.infinityforreddit.API.RedditAPI; +import ml.docilealligator.infinityforreddit.Utils.APIUtils; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +public class FetchMessage { + + 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"; + public static final String WHERE_MESSAGES = "messages"; + public static final String WHERE_MESSAGES_DETAIL = "messages_detail"; + public static final int MESSAGE_TYPE_INBOX = 0; + public static final int MESSAGE_TYPE_PRIVATE_MESSAGE = 1; + public static final int MESSAGE_TYPE_NOTIFICATION = 2; + + static void fetchInbox(Retrofit oauthRetrofit, Locale locale, String accessToken, String where, + String after, int messageType, FetchMessagesListener fetchMessagesListener) { + oauthRetrofit.create(RedditAPI.class).getMessages(APIUtils.getOAuthHeader(accessToken), where, after) + .enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + ParseMessage.parseMessage(response.body(), locale, messageType, fetchMessagesListener::fetchSuccess); + } else { + fetchMessagesListener.fetchFailed(); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + fetchMessagesListener.fetchFailed(); + } + }); + } + + interface FetchMessagesListener { + void fetchSuccess(ArrayList messages, @Nullable String after); + + void fetchFailed(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Message/Message.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/Message.java new file mode 100644 index 00000000..a53b11f2 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/Message.java @@ -0,0 +1,213 @@ +package ml.docilealligator.infinityforreddit.Message; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; + +public class Message implements Parcelable { + public static final String TYPE_COMMENT = "t1"; + public static final String TYPE_ACCOUNT = "t2"; + public static final String TYPE_LINK = "t3"; + public static final String TYPE_MESSAGE = "t4"; + public static final String TYPE_SUBREDDIT = "t5"; + static final String TYPE_AWARD = "t6"; + + private String kind; + private String subredditName; + private String subredditNamePrefixed; + private String id; + private String fullname; + private String subject; + private String author; + private String parentFullName; + private String title; + private String body; + private String context; + private String distinguished; + private String formattedTime; + private boolean wasComment; + private boolean isNew; + private int score; + private int nComments; + private long timeUTC; + private ArrayList replies; + + Message(String kind, String subredditName, String subredditNamePrefixed, String id, String fullname, + String subject, String author, String parentFullName, String title, String body, String context, + String distinguished, String formattedTime, boolean wasComment, boolean isNew, int score, + int nComments, long timeUTC) { + this.kind = kind; + this.subredditName = subredditName; + this.subredditNamePrefixed = subredditNamePrefixed; + this.id = id; + this.fullname = fullname; + this.subject = subject; + this.author = author; + this.parentFullName = parentFullName; + this.title = title; + this.body = body; + this.context = context; + this.distinguished = distinguished; + this.formattedTime = formattedTime; + this.wasComment = wasComment; + this.isNew = isNew; + this.score = score; + this.nComments = nComments; + this.timeUTC = timeUTC; + } + + + protected Message(Parcel in) { + kind = in.readString(); + subredditName = in.readString(); + subredditNamePrefixed = in.readString(); + id = in.readString(); + fullname = in.readString(); + subject = in.readString(); + author = in.readString(); + parentFullName = in.readString(); + title = in.readString(); + body = in.readString(); + context = in.readString(); + distinguished = in.readString(); + formattedTime = in.readString(); + wasComment = in.readByte() != 0; + isNew = in.readByte() != 0; + score = in.readInt(); + nComments = in.readInt(); + timeUTC = in.readLong(); + replies = in.createTypedArrayList(Message.CREATOR); + } + + public static final Creator CREATOR = new Creator() { + @Override + public Message createFromParcel(Parcel in) { + return new Message(in); + } + + @Override + public Message[] newArray(int size) { + return new Message[size]; + } + }; + + public String getKind() { + return kind; + } + + public String getSubredditName() { + return subredditName; + } + + public String getSubredditNamePrefixed() { + return subredditNamePrefixed; + } + + public String getId() { + return id; + } + + public String getFullname() { + return fullname; + } + + public String getSubject() { + return subject; + } + + public String getAuthor() { + return author; + } + + public String getParentFullName() { + return parentFullName; + } + + public String getTitle() { + return title; + } + + public String getBody() { + return body; + } + + public String getContext() { + return context; + } + + public String getDistinguished() { + return distinguished; + } + + public String getFormattedTime() { + return formattedTime; + } + + public boolean wasComment() { + return wasComment; + } + + public boolean isNew() { + return isNew; + } + + public void setNew(boolean isNew) { + this.isNew = isNew; + } + + public int getScore() { + return score; + } + + public int getnComments() { + return nComments; + } + + public long getTimeUTC() { + return timeUTC; + } + + public ArrayList getReplies() { + return replies; + } + + public void setReplies(ArrayList replies) { + this.replies = replies; + } + + public void addReply(Message reply) { + if (replies == null) { + replies = new ArrayList<>(); + } + replies.add(reply); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int i) { + parcel.writeString(kind); + parcel.writeString(subredditName); + parcel.writeString(subredditNamePrefixed); + parcel.writeString(id); + parcel.writeString(fullname); + parcel.writeString(subject); + parcel.writeString(author); + parcel.writeString(parentFullName); + parcel.writeString(title); + parcel.writeString(body); + parcel.writeString(context); + parcel.writeString(distinguished); + parcel.writeString(formattedTime); + parcel.writeByte((byte) (wasComment ? 1 : 0)); + parcel.writeByte((byte) (isNew ? 1 : 0)); + parcel.writeInt(score); + parcel.writeInt(nComments); + parcel.writeLong(timeUTC); + parcel.writeTypedList(replies); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Message/MessageDataSource.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/MessageDataSource.java new file mode 100644 index 00000000..e3f8cc18 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/MessageDataSource.java @@ -0,0 +1,119 @@ +package ml.docilealligator.infinityforreddit.Message; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.MutableLiveData; +import androidx.paging.PageKeyedDataSource; + +import java.util.ArrayList; +import java.util.Locale; + +import ml.docilealligator.infinityforreddit.NetworkState; +import retrofit2.Retrofit; + +class MessageDataSource extends PageKeyedDataSource { + private Retrofit oauthRetrofit; + private Locale locale; + private String accessToken; + private String where; + private int messageType; + + private MutableLiveData paginationNetworkStateLiveData; + private MutableLiveData initialLoadStateLiveData; + private MutableLiveData hasPostLiveData; + + private LoadParams params; + private LoadCallback callback; + + MessageDataSource(Retrofit oauthRetrofit, Locale locale, String accessToken, String where) { + this.oauthRetrofit = oauthRetrofit; + this.locale = locale; + this.accessToken = accessToken; + this.where = where; + if (where.equals(FetchMessage.WHERE_MESSAGES)) { + messageType = FetchMessage.MESSAGE_TYPE_PRIVATE_MESSAGE; + } else { + messageType = FetchMessage.MESSAGE_TYPE_INBOX; + } + paginationNetworkStateLiveData = new MutableLiveData<>(); + initialLoadStateLiveData = new MutableLiveData<>(); + hasPostLiveData = new MutableLiveData<>(); + } + + MutableLiveData getPaginationNetworkStateLiveData() { + return paginationNetworkStateLiveData; + } + + MutableLiveData getInitialLoadStateLiveData() { + return initialLoadStateLiveData; + } + + MutableLiveData hasPostLiveData() { + return hasPostLiveData; + } + + void retryLoadingMore() { + loadAfter(params, callback); + } + + @Override + public void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback callback) { + initialLoadStateLiveData.postValue(NetworkState.LOADING); + + FetchMessage.fetchInbox(oauthRetrofit, locale, accessToken, where, null, messageType, + new FetchMessage.FetchMessagesListener() { + @Override + public void fetchSuccess(ArrayList messages, @Nullable String after) { + if (messages.size() == 0) { + hasPostLiveData.postValue(false); + } else { + hasPostLiveData.postValue(true); + } + + if (after == null || after.equals("") || after.equals("null")) { + callback.onResult(messages, null, null); + } else { + callback.onResult(messages, null, after); + } + initialLoadStateLiveData.postValue(NetworkState.LOADED); + } + + @Override + public void fetchFailed() { + initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error fetch messages")); + } + }); + } + + @Override + public void loadBefore(@NonNull LoadParams params, @NonNull LoadCallback callback) { + + } + + @Override + public void loadAfter(@NonNull LoadParams params, @NonNull LoadCallback callback) { + this.params = params; + this.callback = callback; + + paginationNetworkStateLiveData.postValue(NetworkState.LOADING); + + FetchMessage.fetchInbox(oauthRetrofit, locale, accessToken, where, params.key, messageType, + new FetchMessage.FetchMessagesListener() { + @Override + public void fetchSuccess(ArrayList messages, @Nullable String after) { + if (after == null || after.equals("") || after.equals("null")) { + callback.onResult(messages, null); + } else { + callback.onResult(messages, after); + } + + paginationNetworkStateLiveData.postValue(NetworkState.LOADED); + } + + @Override + public void fetchFailed() { + paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error fetching data")); + } + }); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Message/MessageDataSourceFactory.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/MessageDataSourceFactory.java new file mode 100644 index 00000000..db717ce5 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/MessageDataSourceFactory.java @@ -0,0 +1,47 @@ +package ml.docilealligator.infinityforreddit.Message; + +import androidx.annotation.NonNull; +import androidx.lifecycle.MutableLiveData; +import androidx.paging.DataSource; + +import java.util.Locale; + +import retrofit2.Retrofit; + +class MessageDataSourceFactory extends DataSource.Factory { + private Retrofit oauthRetrofit; + private Locale locale; + private String accessToken; + private String where; + + private MessageDataSource messageDataSource; + private MutableLiveData messageDataSourceLiveData; + + MessageDataSourceFactory(Retrofit oauthRetrofit, Locale locale, String accessToken, String where) { + this.oauthRetrofit = oauthRetrofit; + this.locale = locale; + this.accessToken = accessToken; + this.where = where; + messageDataSourceLiveData = new MutableLiveData<>(); + } + + @NonNull + @Override + public DataSource create() { + messageDataSource = new MessageDataSource(oauthRetrofit, locale, accessToken, where); + messageDataSourceLiveData.postValue(messageDataSource); + return messageDataSource; + } + + public MutableLiveData getMessageDataSourceLiveData() { + return messageDataSourceLiveData; + } + + MessageDataSource getMessageDataSource() { + return messageDataSource; + } + + void changeWhere(String where) { + this.where = where; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Message/MessageViewModel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/MessageViewModel.java new file mode 100644 index 00000000..3af6b708 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/MessageViewModel.java @@ -0,0 +1,97 @@ +package ml.docilealligator.infinityforreddit.Message; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.Transformations; +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; +import androidx.paging.LivePagedListBuilder; +import androidx.paging.PagedList; + +import java.util.Locale; + +import ml.docilealligator.infinityforreddit.NetworkState; +import retrofit2.Retrofit; + +public class MessageViewModel extends ViewModel { + private MessageDataSourceFactory messageDataSourceFactory; + private LiveData paginationNetworkState; + private LiveData initialLoadingState; + private LiveData hasMessageLiveData; + private LiveData> messages; + private MutableLiveData whereLiveData; + + public MessageViewModel(Retrofit retrofit, Locale locale, String accessToken, String where) { + messageDataSourceFactory = new MessageDataSourceFactory(retrofit, locale, accessToken, where); + + initialLoadingState = Transformations.switchMap(messageDataSourceFactory.getMessageDataSourceLiveData(), + MessageDataSource::getInitialLoadStateLiveData); + paginationNetworkState = Transformations.switchMap(messageDataSourceFactory.getMessageDataSourceLiveData(), + MessageDataSource::getPaginationNetworkStateLiveData); + hasMessageLiveData = Transformations.switchMap(messageDataSourceFactory.getMessageDataSourceLiveData(), + MessageDataSource::hasPostLiveData); + + whereLiveData = new MutableLiveData<>(); + whereLiveData.postValue(where); + + PagedList.Config pagedListConfig = + (new PagedList.Config.Builder()) + .setEnablePlaceholders(false) + .setPageSize(25) + .build(); + + messages = Transformations.switchMap(whereLiveData, newWhere -> { + messageDataSourceFactory.changeWhere(whereLiveData.getValue()); + return (new LivePagedListBuilder(messageDataSourceFactory, pagedListConfig)).build(); + }); + } + + public LiveData> getMessages() { + return messages; + } + + public LiveData getPaginationNetworkState() { + return paginationNetworkState; + } + + public LiveData getInitialLoadingState() { + return initialLoadingState; + } + + public LiveData hasMessage() { + return hasMessageLiveData; + } + + public void refresh() { + messageDataSourceFactory.getMessageDataSource().invalidate(); + } + + public void retryLoadingMore() { + messageDataSourceFactory.getMessageDataSource().retryLoadingMore(); + } + + void changeWhere(String where) { + whereLiveData.postValue(where); + } + + public static class Factory extends ViewModelProvider.NewInstanceFactory { + private Retrofit retrofit; + private Locale locale; + private String accessToken; + private String where; + + public Factory(Retrofit retrofit, Locale locale, String accessToken, String where) { + this.retrofit = retrofit; + this.locale = locale; + this.accessToken = accessToken; + this.where = where; + } + + @NonNull + @Override + public T create(@NonNull Class modelClass) { + return (T) new MessageViewModel(retrofit, locale, accessToken, where); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Message/ParseMessage.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/ParseMessage.java new file mode 100644 index 00000000..6b4048e4 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/ParseMessage.java @@ -0,0 +1,205 @@ +package ml.docilealligator.infinityforreddit.Message; + +import android.os.AsyncTask; + +import androidx.annotation.Nullable; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Locale; + +import ml.docilealligator.infinityforreddit.Utils.JSONUtils; +import ml.docilealligator.infinityforreddit.Utils.Utils; + +public class ParseMessage { + public static void parseMessage(String response, Locale locale, int messageType, + ParseMessageAsyncTaskListener parseMessageAsnycTaskListener) { + new ParseMessageAsnycTask(response, locale, messageType, parseMessageAsnycTaskListener).execute(); + } + + public static ArrayList parseMessages(JSONArray messageArray, Locale locale, int messageType) { + ArrayList messages = new ArrayList<>(); + for (int i = 0; i < messageArray.length(); i++) { + try { + Message message = parseSingleMessage(messageArray.getJSONObject(i), locale, messageType); + if (message != null) { + messages.add(message); + } + } catch (JSONException e) { + e.printStackTrace(); + } + } + return messages; + } + + public static void parseRepliedMessage(String response, Locale locale, ParseSentMessageAsyncTaskListener parseSentMessageAsyncTaskListener) { + new ParseSentMessageAsnycTask(response, locale, parseSentMessageAsyncTaskListener).execute(); + } + + @Nullable + private static Message parseSingleMessage(JSONObject messageJSON, Locale locale, int messageType) throws JSONException { + String kind = messageJSON.getString(JSONUtils.KIND_KEY); + if ((messageType == FetchMessage.MESSAGE_TYPE_INBOX && kind.equals("t4")) || + (messageType == FetchMessage.MESSAGE_TYPE_PRIVATE_MESSAGE && !kind.equals("t4"))) { + return null; + } + + JSONObject rawMessageJSON = messageJSON.getJSONObject(JSONUtils.DATA_KEY); + String subredditName = rawMessageJSON.getString(JSONUtils.SUBREDDIT_KEY); + String subredditNamePrefixed = rawMessageJSON.getString(JSONUtils.SUBREDDIT_NAME_PREFIX_KEY); + String id = rawMessageJSON.getString(JSONUtils.ID_KEY); + String fullname = rawMessageJSON.getString(JSONUtils.NAME_KEY); + String subject = rawMessageJSON.getString(JSONUtils.SUBJECT_KEY); + String author = rawMessageJSON.getString(JSONUtils.AUTHOR_KEY); + String parentFullname = rawMessageJSON.getString(JSONUtils.PARENT_ID_KEY); + String title = rawMessageJSON.has(JSONUtils.LINK_TITLE_KEY) ? rawMessageJSON.getString(JSONUtils.LINK_TITLE_KEY) : null; + String body = Utils.modifyMarkdown(rawMessageJSON.getString(JSONUtils.BODY_KEY)); + String context = rawMessageJSON.getString(JSONUtils.CONTEXT_KEY); + String distinguished = rawMessageJSON.getString(JSONUtils.DISTINGUISHED_KEY); + boolean wasComment = rawMessageJSON.getBoolean(JSONUtils.WAS_COMMENT_KEY); + boolean isNew = rawMessageJSON.getBoolean(JSONUtils.NEW_KEY); + int score = rawMessageJSON.getInt(JSONUtils.SCORE_KEY); + int nComments = rawMessageJSON.isNull(JSONUtils.NUM_COMMENTS_KEY) ? -1 : rawMessageJSON.getInt(JSONUtils.NUM_COMMENTS_KEY); + long timeUTC = rawMessageJSON.getLong(JSONUtils.CREATED_UTC_KEY) * 1000; + + Calendar submitTimeCalendar = Calendar.getInstance(); + submitTimeCalendar.setTimeInMillis(timeUTC); + String formattedTime = new SimpleDateFormat("MMM d, yyyy, HH:mm", + locale).format(submitTimeCalendar.getTime()); + + ArrayList replies = null; + if (!rawMessageJSON.isNull(JSONUtils.REPLIES_KEY) && rawMessageJSON.get(JSONUtils.REPLIES_KEY) instanceof JSONObject) { + JSONArray repliesArray = rawMessageJSON.getJSONObject(JSONUtils.REPLIES_KEY).getJSONObject(JSONUtils.DATA_KEY) + .getJSONArray(JSONUtils.CHILDREN_KEY); + replies = parseMessages(repliesArray, locale, messageType); + } + + Message message = new Message(kind, subredditName, subredditNamePrefixed, id, fullname, subject, + author, parentFullname, title, body, context, distinguished, formattedTime, + wasComment, isNew, score, nComments, timeUTC); + if (replies != null) { + message.setReplies(replies); + } + + return message; + } + + private static class ParseMessageAsnycTask extends AsyncTask { + + private String response; + private Locale locale; + private ArrayList messages; + private String after; + private int messageType; + private ParseMessageAsyncTaskListener parseMessageAsyncTaskListener; + ParseMessageAsnycTask(String response, Locale locale, int messageType, + ParseMessageAsyncTaskListener parseMessageAsnycTaskListener) { + this.response = response; + this.locale = locale; + this.messageType = messageType; + messages = new ArrayList<>(); + this.parseMessageAsyncTaskListener = parseMessageAsnycTaskListener; + } + + @Override + protected Void doInBackground(Void... voids) { + try { + JSONArray messageArray = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); + messages = parseMessages(messageArray, locale, messageType); + after = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.AFTER_KEY); + } catch (JSONException e) { + e.printStackTrace(); + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + parseMessageAsyncTaskListener.parseSuccess(messages, after); + } + } + + private static class ParseSentMessageAsnycTask extends AsyncTask { + + private String response; + private Locale locale; + private Message message; + private String errorMessage; + private boolean parseFailed = false; + private ParseSentMessageAsyncTaskListener parseSentMessageAsyncTaskListener; + + ParseSentMessageAsnycTask(String response, Locale locale, ParseSentMessageAsyncTaskListener parseSentMessageAsyncTaskListener) { + this.response = response; + this.locale = locale; + this.parseSentMessageAsyncTaskListener = parseSentMessageAsyncTaskListener; + } + + @Override + protected Void doInBackground(Void... voids) { + try { + JSONObject messageJSON = new JSONObject(response).getJSONObject(JSONUtils.JSON_KEY) + .getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.THINGS_KEY).getJSONObject(0); + message = parseSingleMessage(messageJSON, locale, FetchMessage.MESSAGE_TYPE_PRIVATE_MESSAGE); + } catch (JSONException e) { + e.printStackTrace(); + errorMessage = parseRepliedMessageErrorMessage(response); + parseFailed = true; + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + if (parseFailed) { + parseSentMessageAsyncTaskListener.parseFailed(errorMessage); + } else { + parseSentMessageAsyncTaskListener.parseSuccess(message); + } + } + } + + @Nullable + private static String parseRepliedMessageErrorMessage(String response) { + try { + JSONObject responseObject = new JSONObject(response).getJSONObject(JSONUtils.JSON_KEY); + + if (responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() != 0) { + JSONArray error = responseObject.getJSONArray(JSONUtils.ERRORS_KEY) + .getJSONArray(responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() - 1); + if (error.length() != 0) { + String errorString; + if (error.length() >= 2) { + errorString = error.getString(1); + } else { + errorString = error.getString(0); + } + return errorString.substring(0, 1).toUpperCase() + errorString.substring(1); + } else { + return null; + } + } else { + return null; + } + } catch (JSONException e) { + e.printStackTrace(); + } + + return null; + } + + public interface ParseMessageAsyncTaskListener { + void parseSuccess(ArrayList messages, @Nullable String after); + } + + public interface ParseSentMessageAsyncTaskListener { + void parseSuccess(Message message); + void parseFailed(String errorMessage); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Message/ReadMessage.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/ReadMessage.java new file mode 100644 index 00000000..bb8b4030 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/ReadMessage.java @@ -0,0 +1,43 @@ +package ml.docilealligator.infinityforreddit.Message; + +import androidx.annotation.NonNull; + +import java.util.HashMap; +import java.util.Map; + +import ml.docilealligator.infinityforreddit.API.RedditAPI; +import ml.docilealligator.infinityforreddit.Utils.APIUtils; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +public class ReadMessage { + public static void readMessage(Retrofit oauthRetrofit, String accessToken, String commaSeparatedFullnames, + ReadMessageListener readMessageListener) { + Map params = new HashMap<>(); + params.put(APIUtils.ID_KEY, commaSeparatedFullnames); + oauthRetrofit.create(RedditAPI.class).readMessage(APIUtils.getOAuthHeader(accessToken), params) + .enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + readMessageListener.readSuccess(); + } else { + readMessageListener.readFailed(); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + readMessageListener.readFailed(); + } + }); + } + + public interface ReadMessageListener { + void readSuccess(); + + void readFailed(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Message/ReplyMessage.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/ReplyMessage.java new file mode 100644 index 00000000..ca8edcd2 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Message/ReplyMessage.java @@ -0,0 +1,58 @@ +package ml.docilealligator.infinityforreddit.Message; + +import androidx.annotation.NonNull; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import ml.docilealligator.infinityforreddit.API.RedditAPI; +import ml.docilealligator.infinityforreddit.Utils.APIUtils; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +public class ReplyMessage { + public static void replyMessage(String messageMarkdown, String thingFullname, + Locale locale, Retrofit oauthRetrofit, String accessToken, + ReplyMessageListener replyMessageListener) { + Map headers = APIUtils.getOAuthHeader(accessToken); + Map params = new HashMap<>(); + params.put(APIUtils.API_TYPE_KEY, "json"); + params.put(APIUtils.RETURN_RTJSON_KEY, "true"); + params.put(APIUtils.TEXT_KEY, messageMarkdown); + params.put(APIUtils.THING_ID_KEY, thingFullname); + + oauthRetrofit.create(RedditAPI.class).sendCommentOrReplyToMessage(headers, params).enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + ParseMessage.parseRepliedMessage(response.body(), locale, new ParseMessage.ParseSentMessageAsyncTaskListener() { + @Override + public void parseSuccess(Message message) { + replyMessageListener.replyMessageSuccess(message); + } + + @Override + public void parseFailed(String errorMessage) { + replyMessageListener.replyMessageFailed(errorMessage); + } + }); + } else { + replyMessageListener.replyMessageFailed(response.message()); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + replyMessageListener.replyMessageFailed(t.getMessage()); + } + }); + } + + public interface ReplyMessageListener { + void replyMessageSuccess(Message message); + void replyMessageFailed(String errorMessage); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MessageDataSource.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MessageDataSource.java deleted file mode 100644 index f81d1894..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/MessageDataSource.java +++ /dev/null @@ -1,118 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.lifecycle.MutableLiveData; -import androidx.paging.PageKeyedDataSource; - -import java.util.ArrayList; -import java.util.Locale; - -import retrofit2.Retrofit; - -class MessageDataSource extends PageKeyedDataSource { - private Retrofit oauthRetrofit; - private Locale locale; - private String accessToken; - private String where; - private int messageType; - - private MutableLiveData paginationNetworkStateLiveData; - private MutableLiveData initialLoadStateLiveData; - private MutableLiveData hasPostLiveData; - - private LoadParams params; - private LoadCallback callback; - - MessageDataSource(Retrofit oauthRetrofit, Locale locale, String accessToken, String where) { - this.oauthRetrofit = oauthRetrofit; - this.locale = locale; - this.accessToken = accessToken; - this.where = where; - if (where.equals(FetchMessages.WHERE_MESSAGES)) { - messageType = FetchMessages.MESSAGE_TYPE_PRIVATE_MESSAGE; - } else { - messageType = FetchMessages.MESSAGE_TYPE_INBOX; - } - paginationNetworkStateLiveData = new MutableLiveData<>(); - initialLoadStateLiveData = new MutableLiveData<>(); - hasPostLiveData = new MutableLiveData<>(); - } - - MutableLiveData getPaginationNetworkStateLiveData() { - return paginationNetworkStateLiveData; - } - - MutableLiveData getInitialLoadStateLiveData() { - return initialLoadStateLiveData; - } - - MutableLiveData hasPostLiveData() { - return hasPostLiveData; - } - - void retryLoadingMore() { - loadAfter(params, callback); - } - - @Override - public void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback callback) { - initialLoadStateLiveData.postValue(NetworkState.LOADING); - - FetchMessages.fetchInbox(oauthRetrofit, locale, accessToken, where, null, messageType, - new FetchMessages.FetchMessagesListener() { - @Override - public void fetchSuccess(ArrayList messages, @Nullable String after) { - if (messages.size() == 0) { - hasPostLiveData.postValue(false); - } else { - hasPostLiveData.postValue(true); - } - - if (after == null || after.equals("") || after.equals("null")) { - callback.onResult(messages, null, null); - } else { - callback.onResult(messages, null, after); - } - initialLoadStateLiveData.postValue(NetworkState.LOADED); - } - - @Override - public void fetchFailed() { - initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error fetch messages")); - } - }); - } - - @Override - public void loadBefore(@NonNull LoadParams params, @NonNull LoadCallback callback) { - - } - - @Override - public void loadAfter(@NonNull LoadParams params, @NonNull LoadCallback callback) { - this.params = params; - this.callback = callback; - - paginationNetworkStateLiveData.postValue(NetworkState.LOADING); - - FetchMessages.fetchInbox(oauthRetrofit, locale, accessToken, where, params.key, messageType, - new FetchMessages.FetchMessagesListener() { - @Override - public void fetchSuccess(ArrayList messages, @Nullable String after) { - if (after == null || after.equals("") || after.equals("null")) { - callback.onResult(messages, null); - } else { - callback.onResult(messages, after); - } - - paginationNetworkStateLiveData.postValue(NetworkState.LOADED); - } - - @Override - public void fetchFailed() { - paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error fetching data")); - } - }); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MessageDataSourceFactory.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MessageDataSourceFactory.java deleted file mode 100644 index b1470bf7..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/MessageDataSourceFactory.java +++ /dev/null @@ -1,47 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import androidx.annotation.NonNull; -import androidx.lifecycle.MutableLiveData; -import androidx.paging.DataSource; - -import java.util.Locale; - -import retrofit2.Retrofit; - -class MessageDataSourceFactory extends DataSource.Factory { - private Retrofit oauthRetrofit; - private Locale locale; - private String accessToken; - private String where; - - private MessageDataSource messageDataSource; - private MutableLiveData messageDataSourceLiveData; - - MessageDataSourceFactory(Retrofit oauthRetrofit, Locale locale, String accessToken, String where) { - this.oauthRetrofit = oauthRetrofit; - this.locale = locale; - this.accessToken = accessToken; - this.where = where; - messageDataSourceLiveData = new MutableLiveData<>(); - } - - @NonNull - @Override - public DataSource create() { - messageDataSource = new MessageDataSource(oauthRetrofit, locale, accessToken, where); - messageDataSourceLiveData.postValue(messageDataSource); - return messageDataSource; - } - - public MutableLiveData getMessageDataSourceLiveData() { - return messageDataSourceLiveData; - } - - MessageDataSource getMessageDataSource() { - return messageDataSource; - } - - void changeWhere(String where) { - this.where = where; - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MessageViewModel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MessageViewModel.java deleted file mode 100644 index e02c4296..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/MessageViewModel.java +++ /dev/null @@ -1,96 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import androidx.annotation.NonNull; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.Transformations; -import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; -import androidx.paging.LivePagedListBuilder; -import androidx.paging.PagedList; - -import java.util.Locale; - -import retrofit2.Retrofit; - -public class MessageViewModel extends ViewModel { - private MessageDataSourceFactory messageDataSourceFactory; - private LiveData paginationNetworkState; - private LiveData initialLoadingState; - private LiveData hasMessageLiveData; - private LiveData> messages; - private MutableLiveData whereLiveData; - - public MessageViewModel(Retrofit retrofit, Locale locale, String accessToken, String where) { - messageDataSourceFactory = new MessageDataSourceFactory(retrofit, locale, accessToken, where); - - initialLoadingState = Transformations.switchMap(messageDataSourceFactory.getMessageDataSourceLiveData(), - MessageDataSource::getInitialLoadStateLiveData); - paginationNetworkState = Transformations.switchMap(messageDataSourceFactory.getMessageDataSourceLiveData(), - MessageDataSource::getPaginationNetworkStateLiveData); - hasMessageLiveData = Transformations.switchMap(messageDataSourceFactory.getMessageDataSourceLiveData(), - MessageDataSource::hasPostLiveData); - - whereLiveData = new MutableLiveData<>(); - whereLiveData.postValue(where); - - PagedList.Config pagedListConfig = - (new PagedList.Config.Builder()) - .setEnablePlaceholders(false) - .setPageSize(25) - .build(); - - messages = Transformations.switchMap(whereLiveData, newWhere -> { - messageDataSourceFactory.changeWhere(whereLiveData.getValue()); - return (new LivePagedListBuilder(messageDataSourceFactory, pagedListConfig)).build(); - }); - } - - public LiveData> getMessages() { - return messages; - } - - public LiveData getPaginationNetworkState() { - return paginationNetworkState; - } - - public LiveData getInitialLoadingState() { - return initialLoadingState; - } - - public LiveData hasMessage() { - return hasMessageLiveData; - } - - public void refresh() { - messageDataSourceFactory.getMessageDataSource().invalidate(); - } - - public void retryLoadingMore() { - messageDataSourceFactory.getMessageDataSource().retryLoadingMore(); - } - - void changeWhere(String where) { - whereLiveData.postValue(where); - } - - public static class Factory extends ViewModelProvider.NewInstanceFactory { - private Retrofit retrofit; - private Locale locale; - private String accessToken; - private String where; - - public Factory(Retrofit retrofit, Locale locale, String accessToken, String where) { - this.retrofit = retrofit; - this.locale = locale; - this.accessToken = accessToken; - this.where = where; - } - - @NonNull - @Override - public T create(@NonNull Class modelClass) { - return (T) new MessageViewModel(retrofit, locale, accessToken, where); - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java deleted file mode 100644 index 272294ba..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java +++ /dev/null @@ -1,322 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.AsyncTask; -import android.text.Html; - -import androidx.annotation.Nullable; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; -import java.util.Locale; - -import ml.docilealligator.infinityforreddit.Utils.JSONUtils; -import ml.docilealligator.infinityforreddit.Utils.Utils; - -import static ml.docilealligator.infinityforreddit.CommentData.VOTE_TYPE_DOWNVOTE; -import static ml.docilealligator.infinityforreddit.CommentData.VOTE_TYPE_NO_VOTE; -import static ml.docilealligator.infinityforreddit.CommentData.VOTE_TYPE_UPVOTE; - -public class ParseComment { - public static void parseComment(String response, ArrayList commentData, Locale locale, - boolean expandChildren, ParseCommentListener parseCommentListener) { - try { - JSONArray childrenArray = new JSONArray(response); - String parentId = childrenArray.getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY) - .getJSONObject(0).getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.NAME_KEY); - childrenArray = childrenArray.getJSONObject(1).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); - - new ParseCommentAsyncTask(childrenArray, commentData, locale, parentId, 0, expandChildren, parseCommentListener).execute(); - } catch (JSONException e) { - e.printStackTrace(); - parseCommentListener.onParseCommentFailed(); - } - } - - static void parseMoreComment(String response, ArrayList commentData, Locale locale, - int depth, boolean expandChildren, ParseCommentListener parseCommentListener) { - try { - JSONArray childrenArray = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); - new ParseCommentAsyncTask(childrenArray, commentData, locale, null, depth, expandChildren, parseCommentListener).execute(); - } catch (JSONException e) { - e.printStackTrace(); - parseCommentListener.onParseCommentFailed(); - } - } - - static void parseSentComment(String response, int depth, Locale locale, - ParseSentCommentListener parseSentCommentListener) { - new ParseSentCommentAsyncTask(response, depth, locale, parseSentCommentListener).execute(); - } - - private static void parseCommentRecursion(JSONArray comments, ArrayList newCommentData, - ArrayList moreChildrenFullnames, int depth, Locale locale) throws JSONException { - int actualCommentLength; - - if (comments.length() == 0) { - return; - } - - JSONObject more = comments.getJSONObject(comments.length() - 1).getJSONObject(JSONUtils.DATA_KEY); - - //Maybe moreChildrenFullnames contain only commentsJSONArray and no more info - if (more.has(JSONUtils.COUNT_KEY)) { - JSONArray childrenArray = more.getJSONArray(JSONUtils.CHILDREN_KEY); - - for (int i = 0; i < childrenArray.length(); i++) { - moreChildrenFullnames.add("t1_" + childrenArray.getString(i)); - } - - actualCommentLength = comments.length() - 1; - } else { - actualCommentLength = comments.length(); - } - - for (int i = 0; i < actualCommentLength; i++) { - JSONObject data = comments.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY); - CommentData singleComment = parseSingleComment(data, depth, locale); - - if (data.get(JSONUtils.REPLIES_KEY) instanceof JSONObject) { - JSONArray childrenArray = data.getJSONObject(JSONUtils.REPLIES_KEY) - .getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); - ArrayList children = new ArrayList<>(); - ArrayList nextMoreChildrenFullnames = new ArrayList<>(); - parseCommentRecursion(childrenArray, children, nextMoreChildrenFullnames, singleComment.getDepth(), - locale); - singleComment.addChildren(children); - singleComment.setMoreChildrenFullnames(nextMoreChildrenFullnames); - } - - newCommentData.add(singleComment); - } - } - - private static void expandChildren(ArrayList comments, ArrayList visibleComments, - boolean setExpanded) { - for (CommentData c : comments) { - visibleComments.add(c); - if (c.hasReply()) { - if (setExpanded) { - c.setExpanded(true); - } - expandChildren(c.getChildren(), visibleComments, setExpanded); - } - if (c.hasMoreChildrenFullnames() && c.getMoreChildrenFullnames().size() > c.getMoreChildrenStartingIndex()) { - //Add a load more placeholder - CommentData placeholder = new CommentData(c.getFullName(), c.getDepth() + 1); - visibleComments.add(placeholder); - c.addChild(placeholder, c.getChildren().size()); - } - } - } - - static CommentData parseSingleComment(JSONObject singleCommentData, int depth, Locale locale) throws JSONException { - String id = singleCommentData.getString(JSONUtils.ID_KEY); - String fullName = singleCommentData.getString(JSONUtils.NAME_KEY); - String author = singleCommentData.getString(JSONUtils.AUTHOR_KEY); - StringBuilder authorFlairHTMLBuilder = new StringBuilder(); - if (singleCommentData.has(JSONUtils.AUTHOR_FLAIR_RICHTEXT_KEY)) { - JSONArray flairArray = singleCommentData.getJSONArray(JSONUtils.AUTHOR_FLAIR_RICHTEXT_KEY); - for (int i = 0; i < flairArray.length(); i++) { - JSONObject flairObject = flairArray.getJSONObject(i); - String e = flairObject.getString(JSONUtils.E_KEY); - if (e.equals("text")) { - authorFlairHTMLBuilder.append(Html.escapeHtml(flairObject.getString(JSONUtils.T_KEY))); - } else if (e.equals("emoji")) { - authorFlairHTMLBuilder.append(""); - } - } - } - String authorFlair = singleCommentData.isNull(JSONUtils.AUTHOR_FLAIR_TEXT_KEY) ? "" : singleCommentData.getString(JSONUtils.AUTHOR_FLAIR_TEXT_KEY); - String linkAuthor = singleCommentData.has(JSONUtils.LINK_AUTHOR_KEY) ? singleCommentData.getString(JSONUtils.LINK_AUTHOR_KEY) : null; - String linkId = singleCommentData.getString(JSONUtils.LINK_ID_KEY).substring(3); - String subredditName = singleCommentData.getString(JSONUtils.SUBREDDIT_KEY); - String parentId = singleCommentData.getString(JSONUtils.PARENT_ID_KEY); - boolean isSubmitter = singleCommentData.getBoolean(JSONUtils.IS_SUBMITTER_KEY); - String distinguished = singleCommentData.getString(JSONUtils.DISTINGUISHED_KEY); - String commentMarkdown = ""; - if (!singleCommentData.isNull(JSONUtils.BODY_KEY)) { - commentMarkdown = Utils.modifyMarkdown(singleCommentData.getString(JSONUtils.BODY_KEY).trim()); - } - String commentRawText = Utils.trimTrailingWhitespace( - Html.fromHtml(singleCommentData.getString(JSONUtils.BODY_HTML_KEY))).toString(); - String permalink = Html.fromHtml(singleCommentData.getString(JSONUtils.PERMALINK_KEY)).toString(); - StringBuilder awardingsBuilder = new StringBuilder(); - JSONArray awardingsArray = singleCommentData.getJSONArray(JSONUtils.ALL_AWARDINGS_KEY); - for (int i = 0; i < awardingsArray.length(); i++) { - JSONObject award = awardingsArray.getJSONObject(i); - int count = award.getInt(JSONUtils.COUNT_KEY); - JSONArray icons = award.getJSONArray(JSONUtils.RESIZED_ICONS_KEY); - if (icons.length() > 4) { - String iconUrl = icons.getJSONObject(3).getString(JSONUtils.URL_KEY); - awardingsBuilder.append(" ").append("x").append(count).append(" "); - } else if (icons.length() > 0) { - String iconUrl = icons.getJSONObject(icons.length() - 1).getString(JSONUtils.URL_KEY); - awardingsBuilder.append(" ").append("x").append(count).append(" "); - } - } - int score = singleCommentData.getInt(JSONUtils.SCORE_KEY); - int voteType; - if (singleCommentData.isNull(JSONUtils.LIKES_KEY)) { - voteType = VOTE_TYPE_NO_VOTE; - } else { - voteType = singleCommentData.getBoolean(JSONUtils.LIKES_KEY) ? VOTE_TYPE_UPVOTE : VOTE_TYPE_DOWNVOTE; - score -= voteType; - } - long submitTime = singleCommentData.getLong(JSONUtils.CREATED_UTC_KEY) * 1000; - boolean scoreHidden = singleCommentData.getBoolean(JSONUtils.SCORE_HIDDEN_KEY); - boolean saved = singleCommentData.getBoolean(JSONUtils.SAVED_KEY); - - if (singleCommentData.has(JSONUtils.DEPTH_KEY)) { - depth = singleCommentData.getInt(JSONUtils.DEPTH_KEY); - } - - boolean collapsed = singleCommentData.getBoolean(JSONUtils.COLLAPSED_KEY); - boolean hasReply = !(singleCommentData.get(JSONUtils.REPLIES_KEY) instanceof String); - - return new CommentData(id, fullName, author, authorFlair, authorFlairHTMLBuilder.toString(), - linkAuthor, submitTime, commentMarkdown, commentRawText, - linkId, subredditName, parentId, score, voteType, isSubmitter, distinguished, - permalink, awardingsBuilder.toString(),depth, collapsed, hasReply, scoreHidden, saved); - } - - @Nullable - private static String parseSentCommentErrorMessage(String response) { - try { - JSONObject responseObject = new JSONObject(response).getJSONObject(JSONUtils.JSON_KEY); - - if (responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() != 0) { - JSONArray error = responseObject.getJSONArray(JSONUtils.ERRORS_KEY) - .getJSONArray(responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() - 1); - if (error.length() != 0) { - String errorString; - if (error.length() >= 2) { - errorString = error.getString(1); - } else { - errorString = error.getString(0); - } - return errorString.substring(0, 1).toUpperCase() + errorString.substring(1); - } else { - return null; - } - } else { - return null; - } - } catch (JSONException e) { - e.printStackTrace(); - } - - return null; - } - - public interface ParseCommentListener { - void onParseCommentSuccess(ArrayList expandedComments, String parentId, - ArrayList moreChildrenFullnames); - - void onParseCommentFailed(); - } - - interface ParseSentCommentListener { - void onParseSentCommentSuccess(CommentData commentData); - - void onParseSentCommentFailed(@Nullable String errorMessage); - } - - private static class ParseCommentAsyncTask extends AsyncTask { - private JSONArray commentsJSONArray; - private ArrayList comments; - private ArrayList newComments; - private ArrayList expandedNewComments; - private ArrayList moreChildrenFullnames; - private Locale locale; - private String parentId; - private int depth; - private boolean expandChildren; - private ParseCommentListener parseCommentListener; - private boolean parseFailed; - - ParseCommentAsyncTask(JSONArray commentsJSONArray, ArrayList comments, Locale locale, - @Nullable String parentId, int depth, boolean expandChildren, - ParseCommentListener parseCommentListener) { - this.commentsJSONArray = commentsJSONArray; - this.comments = comments; - newComments = new ArrayList<>(); - expandedNewComments = new ArrayList<>(); - moreChildrenFullnames = new ArrayList<>(); - this.locale = locale; - this.parentId = parentId; - this.depth = depth; - this.expandChildren = expandChildren; - parseFailed = false; - this.parseCommentListener = parseCommentListener; - } - - @Override - protected Void doInBackground(Void... voids) { - try { - parseCommentRecursion(commentsJSONArray, newComments, moreChildrenFullnames, depth, locale); - expandChildren(newComments, expandedNewComments, expandChildren); - } catch (JSONException e) { - parseFailed = true; - } - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - if (!parseFailed) { - if (expandChildren) { - comments.addAll(expandedNewComments); - } else { - comments.addAll(newComments); - } - parseCommentListener.onParseCommentSuccess(comments, parentId, moreChildrenFullnames); - } else { - parseCommentListener.onParseCommentFailed(); - } - } - } - - private static class ParseSentCommentAsyncTask extends AsyncTask { - private String response; - private int depth; - private Locale locale; - private ParseSentCommentListener parseSentCommentListener; - private boolean parseFailed; - private String errorMessage; - private CommentData commentData; - - ParseSentCommentAsyncTask(String response, int depth, Locale locale, ParseSentCommentListener parseSentCommentListener) { - this.response = response; - this.depth = depth; - this.locale = locale; - this.parseSentCommentListener = parseSentCommentListener; - parseFailed = false; - } - - @Override - protected Void doInBackground(Void... voids) { - try { - JSONObject sentCommentData = new JSONObject(response); - commentData = parseSingleComment(sentCommentData, depth, locale); - } catch (JSONException e) { - e.printStackTrace(); - errorMessage = parseSentCommentErrorMessage(response); - parseFailed = true; - } - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - if (parseFailed) { - parseSentCommentListener.onParseSentCommentFailed(errorMessage); - } else { - parseSentCommentListener.onParseSentCommentSuccess(commentData); - } - } - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseMessage.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseMessage.java deleted file mode 100644 index c605a5f3..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseMessage.java +++ /dev/null @@ -1,205 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import android.os.AsyncTask; - -import androidx.annotation.Nullable; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Locale; - -import ml.docilealligator.infinityforreddit.Utils.JSONUtils; -import ml.docilealligator.infinityforreddit.Utils.Utils; - -public class ParseMessage { - public static void parseMessage(String response, Locale locale, int messageType, - ParseMessageAsyncTaskListener parseMessageAsnycTaskListener) { - new ParseMessageAsnycTask(response, locale, messageType, parseMessageAsnycTaskListener).execute(); - } - - public static ArrayList parseMessages(JSONArray messageArray, Locale locale, int messageType) { - ArrayList messages = new ArrayList<>(); - for (int i = 0; i < messageArray.length(); i++) { - try { - Message message = parseSingleMessage(messageArray.getJSONObject(i), locale, messageType); - if (message != null) { - messages.add(message); - } - } catch (JSONException e) { - e.printStackTrace(); - } - } - return messages; - } - - public static void parseRepliedMessage(String response, Locale locale, ParseSentMessageAsyncTaskListener parseSentMessageAsyncTaskListener) { - new ParseSentMessageAsnycTask(response, locale, parseSentMessageAsyncTaskListener).execute(); - } - - @Nullable - private static Message parseSingleMessage(JSONObject messageJSON, Locale locale, int messageType) throws JSONException { - String kind = messageJSON.getString(JSONUtils.KIND_KEY); - if ((messageType == FetchMessages.MESSAGE_TYPE_INBOX && kind.equals("t4")) || - (messageType == FetchMessages.MESSAGE_TYPE_PRIVATE_MESSAGE && !kind.equals("t4"))) { - return null; - } - - JSONObject rawMessageJSON = messageJSON.getJSONObject(JSONUtils.DATA_KEY); - String subredditName = rawMessageJSON.getString(JSONUtils.SUBREDDIT_KEY); - String subredditNamePrefixed = rawMessageJSON.getString(JSONUtils.SUBREDDIT_NAME_PREFIX_KEY); - String id = rawMessageJSON.getString(JSONUtils.ID_KEY); - String fullname = rawMessageJSON.getString(JSONUtils.NAME_KEY); - String subject = rawMessageJSON.getString(JSONUtils.SUBJECT_KEY); - String author = rawMessageJSON.getString(JSONUtils.AUTHOR_KEY); - String parentFullname = rawMessageJSON.getString(JSONUtils.PARENT_ID_KEY); - String title = rawMessageJSON.has(JSONUtils.LINK_TITLE_KEY) ? rawMessageJSON.getString(JSONUtils.LINK_TITLE_KEY) : null; - String body = Utils.modifyMarkdown(rawMessageJSON.getString(JSONUtils.BODY_KEY)); - String context = rawMessageJSON.getString(JSONUtils.CONTEXT_KEY); - String distinguished = rawMessageJSON.getString(JSONUtils.DISTINGUISHED_KEY); - boolean wasComment = rawMessageJSON.getBoolean(JSONUtils.WAS_COMMENT_KEY); - boolean isNew = rawMessageJSON.getBoolean(JSONUtils.NEW_KEY); - int score = rawMessageJSON.getInt(JSONUtils.SCORE_KEY); - int nComments = rawMessageJSON.isNull(JSONUtils.NUM_COMMENTS_KEY) ? -1 : rawMessageJSON.getInt(JSONUtils.NUM_COMMENTS_KEY); - long timeUTC = rawMessageJSON.getLong(JSONUtils.CREATED_UTC_KEY) * 1000; - - Calendar submitTimeCalendar = Calendar.getInstance(); - submitTimeCalendar.setTimeInMillis(timeUTC); - String formattedTime = new SimpleDateFormat("MMM d, yyyy, HH:mm", - locale).format(submitTimeCalendar.getTime()); - - ArrayList replies = null; - if (!rawMessageJSON.isNull(JSONUtils.REPLIES_KEY) && rawMessageJSON.get(JSONUtils.REPLIES_KEY) instanceof JSONObject) { - JSONArray repliesArray = rawMessageJSON.getJSONObject(JSONUtils.REPLIES_KEY).getJSONObject(JSONUtils.DATA_KEY) - .getJSONArray(JSONUtils.CHILDREN_KEY); - replies = parseMessages(repliesArray, locale, messageType); - } - - Message message = new Message(kind, subredditName, subredditNamePrefixed, id, fullname, subject, - author, parentFullname, title, body, context, distinguished, formattedTime, - wasComment, isNew, score, nComments, timeUTC); - if (replies != null) { - message.setReplies(replies); - } - - return message; - } - - private static class ParseMessageAsnycTask extends AsyncTask { - - private String response; - private Locale locale; - private ArrayList messages; - private String after; - private int messageType; - private ParseMessageAsyncTaskListener parseMessageAsyncTaskListener; - ParseMessageAsnycTask(String response, Locale locale, int messageType, - ParseMessageAsyncTaskListener parseMessageAsnycTaskListener) { - this.response = response; - this.locale = locale; - this.messageType = messageType; - messages = new ArrayList<>(); - this.parseMessageAsyncTaskListener = parseMessageAsnycTaskListener; - } - - @Override - protected Void doInBackground(Void... voids) { - try { - JSONArray messageArray = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); - messages = parseMessages(messageArray, locale, messageType); - after = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.AFTER_KEY); - } catch (JSONException e) { - e.printStackTrace(); - } - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - parseMessageAsyncTaskListener.parseSuccess(messages, after); - } - } - - private static class ParseSentMessageAsnycTask extends AsyncTask { - - private String response; - private Locale locale; - private Message message; - private String errorMessage; - private boolean parseFailed = false; - private ParseSentMessageAsyncTaskListener parseSentMessageAsyncTaskListener; - - ParseSentMessageAsnycTask(String response, Locale locale, ParseSentMessageAsyncTaskListener parseSentMessageAsyncTaskListener) { - this.response = response; - this.locale = locale; - this.parseSentMessageAsyncTaskListener = parseSentMessageAsyncTaskListener; - } - - @Override - protected Void doInBackground(Void... voids) { - try { - JSONObject messageJSON = new JSONObject(response).getJSONObject(JSONUtils.JSON_KEY) - .getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.THINGS_KEY).getJSONObject(0); - message = parseSingleMessage(messageJSON, locale, FetchMessages.MESSAGE_TYPE_PRIVATE_MESSAGE); - } catch (JSONException e) { - e.printStackTrace(); - errorMessage = parseRepliedMessageErrorMessage(response); - parseFailed = true; - } - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - if (parseFailed) { - parseSentMessageAsyncTaskListener.parseFailed(errorMessage); - } else { - parseSentMessageAsyncTaskListener.parseSuccess(message); - } - } - } - - @Nullable - private static String parseRepliedMessageErrorMessage(String response) { - try { - JSONObject responseObject = new JSONObject(response).getJSONObject(JSONUtils.JSON_KEY); - - if (responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() != 0) { - JSONArray error = responseObject.getJSONArray(JSONUtils.ERRORS_KEY) - .getJSONArray(responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() - 1); - if (error.length() != 0) { - String errorString; - if (error.length() >= 2) { - errorString = error.getString(1); - } else { - errorString = error.getString(0); - } - return errorString.substring(0, 1).toUpperCase() + errorString.substring(1); - } else { - return null; - } - } else { - return null; - } - } catch (JSONException e) { - e.printStackTrace(); - } - - return null; - } - - public interface ParseMessageAsyncTaskListener { - void parseSuccess(ArrayList messages, @Nullable String after); - } - - public interface ParseSentMessageAsyncTaskListener { - void parseSuccess(Message message); - void parseFailed(String errorMessage); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java index 52886ecb..246f9119 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java @@ -31,6 +31,9 @@ import ml.docilealligator.infinityforreddit.Account.Account; import ml.docilealligator.infinityforreddit.Activity.InboxActivity; import ml.docilealligator.infinityforreddit.Activity.LinkResolverActivity; import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper; +import ml.docilealligator.infinityforreddit.Message.FetchMessage; +import ml.docilealligator.infinityforreddit.Message.Message; +import ml.docilealligator.infinityforreddit.Message.ParseMessage; import ml.docilealligator.infinityforreddit.Utils.APIUtils; import ml.docilealligator.infinityforreddit.Utils.JSONUtils; import ml.docilealligator.infinityforreddit.Utils.SharedPreferencesUtils; @@ -85,7 +88,7 @@ public class PullNotificationWorker extends Worker { String responseBody = response.body(); JSONArray messageArray = new JSONObject(responseBody).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); ArrayList messages = ParseMessage.parseMessages(messageArray, - context.getResources().getConfiguration().locale, FetchMessages.MESSAGE_TYPE_NOTIFICATION); + context.getResources().getConfiguration().locale, FetchMessage.MESSAGE_TYPE_NOTIFICATION); if (!messages.isEmpty()) { NotificationManagerCompat notificationManager = NotificationUtils.getNotificationManager(context); @@ -218,7 +221,7 @@ public class PullNotificationWorker extends Worker { Call call = mOauthWithoutAuthenticatorRetrofit.create(RedditAPI.class) .getMessages(APIUtils.getOAuthHeader(account.getAccessToken()), - FetchMessages.WHERE_UNREAD, null); + FetchMessage.WHERE_UNREAD, null); Response response = call.execute(); if (response.isSuccessful()) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ReadMessage.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ReadMessage.java deleted file mode 100644 index 1b039178..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ReadMessage.java +++ /dev/null @@ -1,43 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import androidx.annotation.NonNull; - -import java.util.HashMap; -import java.util.Map; - -import ml.docilealligator.infinityforreddit.API.RedditAPI; -import ml.docilealligator.infinityforreddit.Utils.APIUtils; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -public class ReadMessage { - public static void readMessage(Retrofit oauthRetrofit, String accessToken, String commaSeparatedFullnames, - ReadMessageListener readMessageListener) { - Map params = new HashMap<>(); - params.put(APIUtils.ID_KEY, commaSeparatedFullnames); - oauthRetrofit.create(RedditAPI.class).readMessage(APIUtils.getOAuthHeader(accessToken), params) - .enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - readMessageListener.readSuccess(); - } else { - readMessageListener.readFailed(); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - readMessageListener.readFailed(); - } - }); - } - - public interface ReadMessageListener { - void readSuccess(); - - void readFailed(); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java index 8743c4c9..3bac4b1b 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java @@ -26,7 +26,7 @@ import ml.docilealligator.infinityforreddit.User.UserDao; import ml.docilealligator.infinityforreddit.User.UserData; @Database(entities = {Account.class, SubredditData.class, SubscribedSubredditData.class, UserData.class, - SubscribedUserData.class, MultiReddit.class, CustomTheme.class}, version = 8) + SubscribedUserData.class, MultiReddit.class, CustomTheme.class}, version = 9) public abstract class RedditDataRoomDatabase extends RoomDatabase { private static RedditDataRoomDatabase INSTANCE; @@ -37,7 +37,7 @@ public abstract class RedditDataRoomDatabase extends RoomDatabase { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), RedditDataRoomDatabase.class, "reddit_data") .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5, - MIGRATION_5_6, MIGRATION_6_7, MIGRATION_7_8) + MIGRATION_5_6, MIGRATION_6_7, MIGRATION_7_8, MIGRATION_8_9) .build(); } } @@ -186,4 +186,27 @@ public abstract class RedditDataRoomDatabase extends RoomDatabase { + " ADD COLUMN bottom_app_bar_icon_color INTEGER DEFAULT " + Color.parseColor("#000000") + " NOT NULL"); } }; + + private static final Migration MIGRATION_8_9 = new Migration(8, 9) { + @Override + public void migrate(@NonNull SupportSQLiteDatabase database) { + database.execSQL("ALTER TABLE custom_themes" + + " ADD COLUMN link_color INTEGER DEFAULT " + Color.parseColor("#FF4081") + " NOT NULL"); + database.execSQL("ALTER TABLE custom_themes" + + " ADD COLUMN received_message_text_color INTEGER DEFAULT " + Color.parseColor("#FFFFFF") + " NOT NULL"); + database.execSQL("ALTER TABLE custom_themes" + + " ADD COLUMN sent_message_text_color INTEGER DEFAULT " + Color.parseColor("#FFFFFF") + " NOT NULL"); + database.execSQL("ALTER TABLE custom_themes" + + " ADD COLUMN received_message_background_color INTEGER DEFAULT " + Color.parseColor("#4185F4") + " NOT NULL"); + database.execSQL("ALTER TABLE custom_themes" + + " ADD COLUMN sent_message_background_color INTEGER DEFAULT " + Color.parseColor("#31BF7D") + " NOT NULL"); + database.execSQL("ALTER TABLE custom_themes" + + " ADD COLUMN send_message_icon_color INTEGER DEFAULT " + Color.parseColor("#4185F4") + " NOT NULL"); + database.execSQL("ALTER TABLE custom_themes" + + " ADD COLUMN fully_collapsed_comment_background_color INTEGER DEFAULT " + Color.parseColor("#4185F4") + " NOT NULL"); + database.execSQL("ALTER TABLE custom_themes" + + " ADD COLUMN awarded_comment_background_color INTEGER DEFAULT " + Color.parseColor("#EEAB02") + " NOT NULL"); + + } + }; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ReplyMessage.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ReplyMessage.java deleted file mode 100644 index 1b60d05b..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ReplyMessage.java +++ /dev/null @@ -1,58 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import androidx.annotation.NonNull; - -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import ml.docilealligator.infinityforreddit.API.RedditAPI; -import ml.docilealligator.infinityforreddit.Utils.APIUtils; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -public class ReplyMessage { - public static void replyMessage(String messageMarkdown, String thingFullname, - Locale locale, Retrofit oauthRetrofit, String accessToken, - ReplyMessageListener replyMessageListener) { - Map headers = APIUtils.getOAuthHeader(accessToken); - Map params = new HashMap<>(); - params.put(APIUtils.API_TYPE_KEY, "json"); - params.put(APIUtils.RETURN_RTJSON_KEY, "true"); - params.put(APIUtils.TEXT_KEY, messageMarkdown); - params.put(APIUtils.THING_ID_KEY, thingFullname); - - oauthRetrofit.create(RedditAPI.class).sendCommentOrReplyToMessage(headers, params).enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - ParseMessage.parseRepliedMessage(response.body(), locale, new ParseMessage.ParseSentMessageAsyncTaskListener() { - @Override - public void parseSuccess(Message message) { - replyMessageListener.replyMessageSuccess(message); - } - - @Override - public void parseFailed(String errorMessage) { - replyMessageListener.replyMessageFailed(errorMessage); - } - }); - } else { - replyMessageListener.replyMessageFailed(response.message()); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - replyMessageListener.replyMessageFailed(t.getMessage()); - } - }); - } - - public interface ReplyMessageListener { - void replyMessageSuccess(Message message); - void replyMessageFailed(String errorMessage); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SendComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SendComment.java deleted file mode 100644 index d35d07c7..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SendComment.java +++ /dev/null @@ -1,64 +0,0 @@ -package ml.docilealligator.infinityforreddit; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import ml.docilealligator.infinityforreddit.API.RedditAPI; -import ml.docilealligator.infinityforreddit.Utils.APIUtils; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -public class SendComment { - - 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 = APIUtils.getOAuthHeader(accessToken); - Map params = new HashMap<>(); - params.put(APIUtils.API_TYPE_KEY, "json"); - params.put(APIUtils.RETURN_RTJSON_KEY, "true"); - params.put(APIUtils.TEXT_KEY, commentMarkdown); - params.put(APIUtils.THING_ID_KEY, thingFullname); - api.sendCommentOrReplyToMessage(headers, params); - - Call sendCommentCall = api.sendCommentOrReplyToMessage(headers, params); - sendCommentCall.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - ParseComment.parseSentComment(response.body(), parentDepth, locale, new ParseComment.ParseSentCommentListener() { - @Override - public void onParseSentCommentSuccess(CommentData commentData) { - sendCommentListener.sendCommentSuccess(commentData); - } - - @Override - public void onParseSentCommentFailed(@Nullable String errorMessage) { - sendCommentListener.sendCommentFailed(errorMessage); - } - }); - } else { - sendCommentListener.sendCommentFailed(response.message()); - } - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - sendCommentListener.sendCommentFailed(t.getMessage()); - } - }); - } - - public interface SendCommentListener { - void sendCommentSuccess(CommentData commentData); - - void sendCommentFailed(String errorMessage); - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/CustomThemeSharedPreferencesUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/CustomThemeSharedPreferencesUtils.java index 295013f1..3ed4951b 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/CustomThemeSharedPreferencesUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/CustomThemeSharedPreferencesUtils.java @@ -79,6 +79,14 @@ public class CustomThemeSharedPreferencesUtils { public static final String COMMENT_VERTICAL_BAR_COLOR_7 = "commentVerticalBarColor7"; public static final String FAB_ICON_COLOR = "fabIconColor"; public static final String CHIP_TEXT_COLOR = "chipTextColor"; + public static final String LINK_COLOR = "linkColor"; + public static final String RECEIVED_MESSAGE_TEXT_COLOR = "receivedMessageTextColor"; + public static final String SENT_MESSAGE_TEXT_COLOR = "sentMessageTextColor"; + public static final String RECEIVED_MESSAGE_BACKROUND_COLOR = "receivedMessageBackgroundColor"; + public static final String SENT_MESSAGE_BACKGROUND_COLOR = "sentMessageBackgroundColor"; + public static final String SEND_MESSAGE_ICON_COLOR = "sentMessageIconColor"; + public static final String FULLY_COLLAPSED_COMMENT_BACKGROUND_COLOR = "fullyCollapsedCommentBackgroundColor"; + public static final String AWARDED_COMMENT_BACKGROUND_COLOR = "awardedCommentBackgroundColor"; public static void insertThemeToSharedPreferences(CustomTheme customTheme, SharedPreferences themeSharedPreferences) { SharedPreferences.Editor editor = themeSharedPreferences.edit(); diff --git a/app/src/main/res/layout/item_comment_fully_collapsed.xml b/app/src/main/res/layout/item_comment_fully_collapsed.xml index f77b683c..c11085c5 100644 --- a/app/src/main/res/layout/item_comment_fully_collapsed.xml +++ b/app/src/main/res/layout/item_comment_fully_collapsed.xml @@ -34,7 +34,7 @@ android:fontFamily="?attr/font_family" /> Applied to: Text on button Chip Text Color Applied to: Subscribe Button + Link Color + Applied to: URL + Received Message Text Color + Applied to: Received Private Messages + Sent Message Text Color + Applied to: Sent Private Messages Background Color Applied to: Background of every page and navigation drawer Card View Background Color Applied to: Post background and message background Comment Background Color Applied to: Comment background + Fully-Collapsed Comment Background Color + Applied to: Background of fully-collapsed comments + Awarded Comment Background Color + Applied to: Background of awarded comments + Received Message Background Color + Applied to: Background of received private messages + Sent Message Background Color + Applied to: Background of sent private messages Bottom Navigation Bar Color Applied to: Bottom navigation bar Primary Icon Color @@ -587,6 +601,8 @@ Applied to: Icons and score in comments Floating Action Button Icon Color Applied to: Floating action button icon + Send Message Icon Color + Applied to: send private message icon Toolbar Primary Text and Icon Color Applied to: Primary texts and icons in toolbars Toolbar Secondary Text Color -- cgit v1.2.3