diff options
14 files changed, 190 insertions, 3 deletions
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ReplyNotificationsToggle.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ReplyNotificationsToggle.java new file mode 100644 index 00000000..c5c29dec --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ReplyNotificationsToggle.java @@ -0,0 +1,45 @@ +package ml.docilealligator.infinityforreddit; + +import android.os.Handler; + +import androidx.annotation.NonNull; + +import java.util.HashMap; +import java.util.Map; + +import ml.docilealligator.infinityforreddit.apis.RedditAPI; +import ml.docilealligator.infinityforreddit.comment.Comment; +import ml.docilealligator.infinityforreddit.utils.APIUtils; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +public class ReplyNotificationsToggle { + public static void toggleEnableNotification(Handler handler, Retrofit oauthRetrofit, String accessToken, + Comment comment, SendNotificationListener sendNotificationListener) { + Map<String, String> params = new HashMap<>(); + params.put(APIUtils.ID_KEY, comment.getFullName()); + params.put(APIUtils.STATE_KEY, String.valueOf(!comment.isSendReplies())); + oauthRetrofit.create(RedditAPI.class).toggleRepliesNotification(APIUtils.getOAuthHeader(accessToken), params).enqueue(new Callback<String>() { + @Override + public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) { + if (response.isSuccessful()) { + handler.post(sendNotificationListener::onSuccess); + } else { + handler.post(sendNotificationListener::onError); + } + } + + @Override + public void onFailure(@NonNull Call<String> call, @NonNull Throwable throwable) { + handler.post(sendNotificationListener::onError); + } + }); + } + + public interface SendNotificationListener { + void onSuccess(); + void onError(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewPostDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewPostDetailActivity.java index 0668a892..0271d3a7 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewPostDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewPostDetailActivity.java @@ -424,6 +424,15 @@ public class ViewPostDetailActivity extends BaseActivity implements SortTypeSele } } + public void toggleReplyNotifications(Comment comment, int position) { + if (sectionsPagerAdapter != null) { + ViewPostDetailFragment fragment = sectionsPagerAdapter.getCurrentFragment(); + if (fragment != null) { + fragment.toggleReplyNotifications(comment, position); + } + } + } + public void saveComment(@NonNull Comment comment, int position) { if (comment.isSaved()) { comment.setSaved(false); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java index c9c819a8..c170a56e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java @@ -75,9 +75,9 @@ import ml.docilealligator.infinityforreddit.SortTypeSelectionCallback; import ml.docilealligator.infinityforreddit.account.Account; import ml.docilealligator.infinityforreddit.adapters.SubredditAutocompleteRecyclerViewAdapter; import ml.docilealligator.infinityforreddit.apis.RedditAPI; +import ml.docilealligator.infinityforreddit.asynctasks.AccountManagement; import ml.docilealligator.infinityforreddit.asynctasks.AddSubredditOrUserToMultiReddit; import ml.docilealligator.infinityforreddit.asynctasks.CheckIsFollowingUser; -import ml.docilealligator.infinityforreddit.asynctasks.AccountManagement; import ml.docilealligator.infinityforreddit.bottomsheetfragments.CopyTextBottomSheetFragment; import ml.docilealligator.infinityforreddit.bottomsheetfragments.FABMoreOptionsBottomSheetFragment; import ml.docilealligator.infinityforreddit.bottomsheetfragments.KarmaInfoBottomSheetFragment; @@ -87,6 +87,7 @@ import ml.docilealligator.infinityforreddit.bottomsheetfragments.RandomBottomShe import ml.docilealligator.infinityforreddit.bottomsheetfragments.SortTimeBottomSheetFragment; import ml.docilealligator.infinityforreddit.bottomsheetfragments.UrlMenuBottomSheetFragment; import ml.docilealligator.infinityforreddit.bottomsheetfragments.UserThingSortTypeBottomSheetFragment; +import ml.docilealligator.infinityforreddit.comment.Comment; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customviews.NavigationWrapper; import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr; @@ -1110,6 +1111,10 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele .show(); } + public void toggleReplyNotifications(Comment comment, int position) { + sectionsPagerAdapter.toggleCommentReplyNotification(comment, position); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.view_user_detail_activity, menu); @@ -1737,6 +1742,18 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele } } } + + void toggleCommentReplyNotification(Comment comment, int position) { + if (fragmentManager != null) { + Fragment fragment = fragmentManager.findFragmentByTag("f1"); + if (fragment instanceof CommentsListingFragment) { + ((CommentsListingFragment) fragment).toggleReplyNotifications(comment, position); + return; + } + } + + Toast.makeText(ViewUserDetailActivity.this, R.string.cannot_find_comment, Toast.LENGTH_SHORT).show(); + } } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java index b6178dc1..0397ff4d 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsListingRecyclerViewAdapter.java @@ -373,6 +373,14 @@ public class CommentsListingRecyclerViewAdapter extends PagedListAdapter<Comment } } + public void toggleReplyNotifications(int position) { + Comment comment = getItem(position); + if (comment != null) { + comment.toggleSendReplies(); + notifyItemChanged(position); + } + } + public void setCanStartActivity(boolean canStartActivity) { this.canStartActivity = canStartActivity; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java index d2a46775..7db33144 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CommentsRecyclerViewAdapter.java @@ -1088,6 +1088,15 @@ public class CommentsRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerVi } } + public void toggleReplyNotifications(String fullName, int position) { + if (mVisibleComments != null && position >= 0 && position < mVisibleComments.size()) { + if (mVisibleComments.get(position).getFullName().equals(fullName)) { + mVisibleComments.get(position).toggleSendReplies(); + } + } + //TODO The comment's position may change + } + public int getNextParentCommentPosition(int currentPosition) { if (mVisibleComments != null && !mVisibleComments.isEmpty()) { if (mIsSingleCommentThreadMode) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/apis/RedditAPI.java b/app/src/main/java/ml/docilealligator/infinityforreddit/apis/RedditAPI.java index fdf89e9a..838b714b 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/apis/RedditAPI.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/apis/RedditAPI.java @@ -422,4 +422,8 @@ public interface RedditAPI { @FormUrlEncoded @POST("/api/morechildren.json?raw_json=1&api_type=json") Call<String> moreChildrenOauth(@Field("link_id") String linkId, @Field("children") String children, @Field("sort") SortType.Type sort, @HeaderMap Map<String, String> headers); + + @FormUrlEncoded + @POST("/api/sendreplies") + Call<String> toggleRepliesNotification(@HeaderMap Map<String, String> headers, @FieldMap Map<String, String> params); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/bottomsheetfragments/CommentMoreBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/bottomsheetfragments/CommentMoreBottomSheetFragment.java index 6b0078f6..889de962 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/bottomsheetfragments/CommentMoreBottomSheetFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/bottomsheetfragments/CommentMoreBottomSheetFragment.java @@ -107,6 +107,19 @@ public class CommentMoreBottomSheetFragment extends LandscapeExpandedRoundedBott } }); } + + if (comment.getAuthor().equals(activity.accountName)) { + binding.notificationViewCommentMoreBottomSheetFragment.setVisibility(View.VISIBLE); + binding.notificationViewCommentMoreBottomSheetFragment.setText(comment.isSendReplies() ? R.string.disable_reply_notifications : R.string.enable_reply_notifications); + binding.notificationViewCommentMoreBottomSheetFragment.setOnClickListener(view -> { + dismiss(); + if (activity instanceof ViewPostDetailActivity) { + ((ViewPostDetailActivity) activity).toggleReplyNotifications(comment, bundle.getInt(EXTRA_POSITION)); + } else if (activity instanceof ViewUserDetailActivity) { + ((ViewUserDetailActivity) activity).toggleReplyNotifications(comment, bundle.getInt(EXTRA_POSITION)); + } + }); + } } if (showReplyAndSaveOption) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/comment/Comment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/comment/Comment.java index 2a1f23f4..cd56a03b 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/comment/Comment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/comment/Comment.java @@ -52,6 +52,7 @@ public class Comment implements Parcelable { private boolean hasReply; private boolean scoreHidden; private boolean saved; + private boolean sendReplies; private boolean isExpanded; private boolean hasExpandedBefore; private boolean isFilteredOut; @@ -69,7 +70,7 @@ public class Comment implements Parcelable { String linkId, String subredditName, String parentId, int score, int voteType, boolean isSubmitter, String distinguished, String permalink, int depth, boolean collapsed, boolean hasReply, - boolean scoreHidden, boolean saved, long edited, Map<String, MediaMetadata> mediaMetadataMap) { + boolean scoreHidden, boolean saved, boolean sendReplies, long edited, Map<String, MediaMetadata> mediaMetadataMap) { this.id = id; this.fullName = fullName; this.author = author; @@ -92,6 +93,7 @@ public class Comment implements Parcelable { this.hasReply = hasReply; this.scoreHidden = scoreHidden; this.saved = saved; + this.sendReplies = sendReplies; this.isExpanded = false; this.hasExpandedBefore = false; this.editedTimeMillis = edited; @@ -140,6 +142,8 @@ public class Comment implements Parcelable { collapsed = in.readByte() != 0; hasReply = in.readByte() != 0; scoreHidden = in.readByte() != 0; + saved = in.readByte() != 0; + sendReplies = in.readByte() != 0; isExpanded = in.readByte() != 0; hasExpandedBefore = in.readByte() != 0; isFilteredOut = in.readByte() != 0; @@ -293,6 +297,14 @@ public class Comment implements Parcelable { this.saved = saved; } + public boolean isSendReplies() { + return sendReplies; + } + + public void toggleSendReplies() { + sendReplies = !sendReplies; + } + public boolean isExpanded() { return isExpanded; } @@ -444,6 +456,8 @@ public class Comment implements Parcelable { parcel.writeByte((byte) (collapsed ? 1 : 0)); parcel.writeByte((byte) (hasReply ? 1 : 0)); parcel.writeByte((byte) (scoreHidden ? 1 : 0)); + parcel.writeByte((byte) (saved ? 1 : 0)); + parcel.writeByte((byte) (sendReplies ? 1 : 0)); parcel.writeByte((byte) (isExpanded ? 1 : 0)); parcel.writeByte((byte) (hasExpandedBefore ? 1 : 0)); parcel.writeByte((byte) (isFilteredOut ? 1 : 0)); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/comment/ParseComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/comment/ParseComment.java index 3e0f526d..29d8ad70 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/comment/ParseComment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/comment/ParseComment.java @@ -298,6 +298,7 @@ public class ParseComment { long submitTime = singleCommentData.getLong(JSONUtils.CREATED_UTC_KEY) * 1000; boolean scoreHidden = singleCommentData.getBoolean(JSONUtils.SCORE_HIDDEN_KEY); boolean saved = singleCommentData.getBoolean(JSONUtils.SAVED_KEY); + boolean sendReplies = singleCommentData.getBoolean(JSONUtils.SEND_REPLIES_KEY); if (singleCommentData.has(JSONUtils.DEPTH_KEY)) { depth = singleCommentData.getInt(JSONUtils.DEPTH_KEY); @@ -312,7 +313,7 @@ public class ParseComment { return new Comment(id, fullName, author, authorFlair, authorFlairHTMLBuilder.toString(), linkAuthor, submitTime, commentMarkdown, commentRawText, linkId, subredditName, parentId, score, voteType, isSubmitter, distinguished, - permalink, depth, collapsed, hasReply, scoreHidden, saved, edited, + permalink, depth, collapsed, hasReply, scoreHidden, saved, sendReplies, edited, mediaMetadataMap); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/CommentsListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/CommentsListingFragment.java index 81db03be..98fb14ea 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/CommentsListingFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/CommentsListingFragment.java @@ -10,10 +10,12 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; import android.view.HapticFeedbackConstants; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.core.content.res.ResourcesCompat; @@ -39,10 +41,12 @@ import ml.docilealligator.infinityforreddit.NetworkState; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.RecyclerViewContentScrollingInterface; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.ReplyNotificationsToggle; import ml.docilealligator.infinityforreddit.SortType; import ml.docilealligator.infinityforreddit.account.Account; import ml.docilealligator.infinityforreddit.activities.BaseActivity; import ml.docilealligator.infinityforreddit.adapters.CommentsListingRecyclerViewAdapter; +import ml.docilealligator.infinityforreddit.comment.Comment; import ml.docilealligator.infinityforreddit.comment.CommentViewModel; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed; @@ -401,6 +405,24 @@ public class CommentsListingFragment extends Fragment implements FragmentCommuni } } + public void toggleReplyNotifications(Comment comment, int position) { + ReplyNotificationsToggle.toggleEnableNotification(new Handler(Looper.getMainLooper()), mOauthRetrofit, + mActivity.accessToken, comment, new ReplyNotificationsToggle.SendNotificationListener() { + @Override + public void onSuccess() { + Toast.makeText(mActivity, + comment.isSendReplies() ? R.string.reply_notifications_disabled : R.string.reply_notifications_enabled, + Toast.LENGTH_SHORT).show(); + mAdapter.toggleReplyNotifications(position); + } + + @Override + public void onError() { + Toast.makeText(mActivity, R.string.toggle_reply_notifications_failed, Toast.LENGTH_SHORT).show(); + } + }); + } + @Subscribe public void onChangeNetworkStatusEvent(ChangeNetworkStatusEvent changeNetworkStatusEvent) { if (mAdapter != null) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewPostDetailFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewPostDetailFragment.java index b9826f11..84a566b4 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewPostDetailFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewPostDetailFragment.java @@ -68,6 +68,7 @@ import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; import ml.docilealligator.infinityforreddit.SaveThing; +import ml.docilealligator.infinityforreddit.ReplyNotificationsToggle; import ml.docilealligator.infinityforreddit.SortType; import ml.docilealligator.infinityforreddit.account.Account; import ml.docilealligator.infinityforreddit.activities.CommentActivity; @@ -1807,6 +1808,24 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic .show(); } + public void toggleReplyNotifications(Comment comment, int position) { + ReplyNotificationsToggle.toggleEnableNotification(new Handler(Looper.getMainLooper()), mOauthRetrofit, + activity.accessToken, comment, new ReplyNotificationsToggle.SendNotificationListener() { + @Override + public void onSuccess() { + Toast.makeText(activity, + comment.isSendReplies() ? R.string.reply_notifications_disabled : R.string.reply_notifications_enabled, + Toast.LENGTH_SHORT).show(); + mCommentsAdapter.toggleReplyNotifications(comment.getFullName(), position); + } + + @Override + public void onError() { + Toast.makeText(activity, R.string.toggle_reply_notifications_failed, Toast.LENGTH_SHORT).show(); + } + }); + } + public void changeToNormalThreadMode() { isSingleCommentThreadMode = false; mSingleCommentId = null; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/JSONUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/JSONUtils.java index 32b8a245..54a6c731 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/JSONUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/JSONUtils.java @@ -196,6 +196,7 @@ public class JSONUtils { public static final String P_KEY = "p"; public static final String VARIANTS_KEY = "variants"; public static final String PAGE_KEY = "page"; + public static final String SEND_REPLIES_KEY = "send_replies"; @Nullable public static Map<String, MediaMetadata> parseMediaMetadata(JSONObject data) { diff --git a/app/src/main/res/layout/fragment_comment_more_bottom_sheet.xml b/app/src/main/res/layout/fragment_comment_more_bottom_sheet.xml index 6d2af1a7..ae8d47db 100644 --- a/app/src/main/res/layout/fragment_comment_more_bottom_sheet.xml +++ b/app/src/main/res/layout/fragment_comment_more_bottom_sheet.xml @@ -162,6 +162,25 @@ android:fontFamily="?attr/font_family" app:drawableStartCompat="@drawable/ic_filter_day_night_24dp" /> + <TextView + android:id="@+id/notification_view_comment_more_bottom_sheet_fragment" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?attr/selectableItemBackground" + android:clickable="true" + android:drawablePadding="48dp" + android:focusable="true" + android:gravity="center_vertical" + android:paddingStart="32dp" + android:paddingTop="16dp" + android:paddingEnd="32dp" + android:paddingBottom="16dp" + android:textColor="?attr/primaryTextColor" + android:textSize="?attr/font_default" + android:fontFamily="?attr/font_family" + android:visibility="gone" + app:drawableStartCompat="@drawable/ic_notifications_day_night_24dp" /> + </LinearLayout> </androidx.core.widget.NestedScrollView> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 19007a64..d2e88ef2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1489,5 +1489,11 @@ <string name="content_description_saved">Saved</string> <string name="comment">Comment</string> + <string name="enable_reply_notifications">Receive reply notifications</string> + <string name="disable_reply_notifications">Disable reply notifications</string> + <string name="reply_notifications_enabled">Reply notifications enabled</string> + <string name="reply_notifications_disabled">Reply notifications disabled</string> + <string name="toggle_reply_notifications_failed">Toggle reply notifications failed</string> + <string name="cannot_find_comment">Cannot find comment</string> </resources> |