From ff5a60c8276071db92e4a584f6a155fdb9048f8c Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Thu, 30 Jan 2020 20:38:35 +0800 Subject: Copying comments is now available. Some UI tweaks. --- .../Adapter/CommentAndPostRecyclerViewAdapter.java | 57 ++++----- .../CommentsListingRecyclerViewAdapter.java | 52 +++------ .../infinityforreddit/CommentData.java | 35 ++++-- .../Fragment/CommentMoreBottomSheetFragment.java | 130 +++++++++++++++++++++ .../Fragment/ModifyCommentBottomSheetFragment.java | 88 -------------- .../infinityforreddit/ParseComment.java | 11 +- .../infinityforreddit/Utils/JSONUtils.java | 1 + app/src/main/res/drawable-night/ic_delete_24dp.xml | 9 ++ app/src/main/res/drawable-night/ic_edit_24dp.xml | 9 ++ app/src/main/res/drawable-night/ic_share_24dp.xml | 9 ++ app/src/main/res/drawable/ic_delete_24dp.xml | 9 ++ app/src/main/res/drawable/ic_edit_24dp.xml | 9 ++ app/src/main/res/drawable/ic_share_24dp.xml | 9 ++ .../layout/fragment_comment_more_bottom_sheet.xml | 86 ++++++++++++++ .../fragment_modify_comment_bottom_sheet.xml | 40 ------- app/src/main/res/layout/item_comment.xml | 7 +- app/src/main/res/values/strings.xml | 3 + 17 files changed, 348 insertions(+), 216 deletions(-) create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/CommentMoreBottomSheetFragment.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/ModifyCommentBottomSheetFragment.java create mode 100644 app/src/main/res/drawable-night/ic_delete_24dp.xml create mode 100644 app/src/main/res/drawable-night/ic_edit_24dp.xml create mode 100644 app/src/main/res/drawable-night/ic_share_24dp.xml create mode 100644 app/src/main/res/drawable/ic_delete_24dp.xml create mode 100644 app/src/main/res/drawable/ic_edit_24dp.xml create mode 100644 app/src/main/res/drawable/ic_share_24dp.xml create mode 100644 app/src/main/res/layout/fragment_comment_more_bottom_sheet.xml delete mode 100644 app/src/main/res/layout/fragment_modify_comment_bottom_sheet.xml (limited to 'app/src') 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 b15d9416..9fd8ffc6 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java @@ -1,6 +1,5 @@ package ml.docilealligator.infinityforreddit.Adapter; -import android.content.ActivityNotFoundException; import android.content.Intent; import android.graphics.ColorFilter; import android.graphics.PorterDuff; @@ -74,8 +73,8 @@ import ml.docilealligator.infinityforreddit.CommentData; import ml.docilealligator.infinityforreddit.CustomView.AspectRatioGifImageView; import ml.docilealligator.infinityforreddit.CustomView.MarkwonLinearLayoutManager; import ml.docilealligator.infinityforreddit.FetchComment; +import ml.docilealligator.infinityforreddit.Fragment.CommentMoreBottomSheetFragment; import ml.docilealligator.infinityforreddit.Fragment.CopyTextBottomSheetFragment; -import ml.docilealligator.infinityforreddit.Fragment.ModifyCommentBottomSheetFragment; import ml.docilealligator.infinityforreddit.Fragment.ShareLinkBottomSheetFragment; import ml.docilealligator.infinityforreddit.Post.Post; import ml.docilealligator.infinityforreddit.Post.PostDataSource; @@ -721,7 +720,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter { - ModifyCommentBottomSheetFragment modifyCommentBottomSheetFragment = new ModifyCommentBottomSheetFragment(); - Bundle bundle = new Bundle(); - bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_COMMENT_CONTENT, comment.getCommentContent()); - bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_COMMENT_FULLNAME, comment.getFullName()); - if (mIsSingleCommentThreadMode) { - bundle.putInt(ModifyCommentBottomSheetFragment.EXTRA_POSITION, holder.getAdapterPosition() - 2); - } else { - bundle.putInt(ModifyCommentBottomSheetFragment.EXTRA_POSITION, holder.getAdapterPosition() - 1); - } - modifyCommentBottomSheetFragment.setArguments(bundle); - modifyCommentBottomSheetFragment.show(((AppCompatActivity) mActivity).getSupportFragmentManager(), modifyCommentBottomSheetFragment.getTag()); - }); - } + ((CommentViewHolder) holder).moreButton.setOnClickListener(view -> { + Bundle bundle = new Bundle(); + if (!mPost.isArchived() && !mPost.isLocked() && comment.getAuthor().equals(mAccountName)) { + bundle.putString(CommentMoreBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + } + bundle.putParcelable(CommentMoreBottomSheetFragment.EXTRA_COMMENT, comment); + if (mIsSingleCommentThreadMode) { + bundle.putInt(CommentMoreBottomSheetFragment.EXTRA_POSITION, holder.getAdapterPosition() - 2); + } else { + bundle.putInt(CommentMoreBottomSheetFragment.EXTRA_POSITION, holder.getAdapterPosition() - 1); + } + CommentMoreBottomSheetFragment commentMoreBottomSheetFragment = new CommentMoreBottomSheetFragment(); + commentMoreBottomSheetFragment.setArguments(bundle); + commentMoreBottomSheetFragment.show(mActivity.getSupportFragmentManager(), commentMoreBottomSheetFragment.getTag()); + }); if (comment.hasReply()) { if (comment.isExpanded()) { @@ -838,7 +834,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter { + /*((CommentViewHolder) holder).shareButton.setOnClickListener(view -> { try { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); @@ -1016,7 +1012,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter { if (((CommentViewHolder) holder).expandButton.getVisibility() == View.VISIBLE) { @@ -1500,7 +1496,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter= 0 && position < mVisibleComments.size()) { if (mVisibleComments.get(position).hasReply()) { mVisibleComments.get(position).setAuthor("[deleted]"); - mVisibleComments.get(position).setCommentContent("[deleted]"); + mVisibleComments.get(position).setCommentMarkdown("[deleted]"); if (mIsSingleCommentThreadMode) { notifyItemChanged(position + 2); } else { @@ -1583,7 +1579,7 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter { - ModifyCommentBottomSheetFragment modifyCommentBottomSheetFragment = new ModifyCommentBottomSheetFragment(); - Bundle bundle = new Bundle(); - bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); - bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_COMMENT_CONTENT, comment.getCommentContent()); - bundle.putString(ModifyCommentBottomSheetFragment.EXTRA_COMMENT_FULLNAME, comment.getFullName()); - bundle.putInt(ModifyCommentBottomSheetFragment.EXTRA_POSITION, holder.getAdapterPosition() - 1); - modifyCommentBottomSheetFragment.setArguments(bundle); - modifyCommentBottomSheetFragment.show(((AppCompatActivity) mContext).getSupportFragmentManager(), modifyCommentBottomSheetFragment.getTag()); - }); - } + ((DataViewHolder) holder).moreButton.setOnClickListener(view -> { + Bundle bundle = new Bundle(); + if (comment.getAuthor().equals(mAccountName)) { + bundle.putString(CommentMoreBottomSheetFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + } + bundle.putParcelable(CommentMoreBottomSheetFragment.EXTRA_COMMENT, comment); + bundle.putInt(CommentMoreBottomSheetFragment.EXTRA_POSITION, holder.getAdapterPosition() - 1); + CommentMoreBottomSheetFragment commentMoreBottomSheetFragment = new CommentMoreBottomSheetFragment(); + commentMoreBottomSheetFragment.setArguments(bundle); + commentMoreBottomSheetFragment.show(((AppCompatActivity) mContext).getSupportFragmentManager(), commentMoreBottomSheetFragment.getTag()); + }); ((DataViewHolder) holder).linearLayout.setOnClickListener(view -> { Intent intent = new Intent(mContext, ViewPostDetailActivity.class); @@ -200,17 +197,6 @@ public class CommentsListingRecyclerViewAdapter extends PagedListAdapter ((DataViewHolder) holder).linearLayout.callOnClick()); - ((DataViewHolder) holder).shareButton.setOnClickListener(view -> { - try { - Intent intent = new Intent(Intent.ACTION_SEND); - intent.setType("text/plain"); - intent.putExtra(Intent.EXTRA_TEXT, comment.getPermalink()); - mContext.startActivity(Intent.createChooser(intent, mContext.getString(R.string.share))); - } catch (ActivityNotFoundException e) { - Toast.makeText(mContext, R.string.no_activity_found_for_share, Toast.LENGTH_SHORT).show(); - } - }); - ((DataViewHolder) holder).replyButton.setVisibility(View.GONE); ((DataViewHolder) holder).upvoteButton.setOnClickListener(view -> { @@ -441,8 +427,6 @@ public class CommentsListingRecyclerViewAdapter extends PagedListAdapter= Build.VERSION_CODES.O + && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + + Bundle bundle = getArguments(); + CommentData commentData = bundle.getParcelable(EXTRA_COMMENT); + if (commentData == null) { + dismiss(); + return rootView; + } + String accessToken = bundle.getString(EXTRA_ACCESS_TOKEN); + + if (accessToken != null && !accessToken.equals("")) { + editTextView.setVisibility(View.VISIBLE); + deleteTextView.setVisibility(View.VISIBLE); + + editTextView.setOnClickListener(view -> { + 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_POSITION, bundle.getInt(EXTRA_POSITION)); + if (activity instanceof ViewPostDetailActivity) { + activity.startActivityForResult(intent, ViewPostDetailActivity.EDIT_COMMENT_REQUEST_CODE); + } else { + startActivity(intent); + } + + dismiss(); + }); + + deleteTextView.setOnClickListener(view -> { + dismiss(); + if (activity instanceof ViewPostDetailActivity) { + ((ViewPostDetailActivity) activity).deleteComment(commentData.getFullName(), bundle.getInt(EXTRA_POSITION)); + } else if (activity instanceof ViewUserDetailActivity) { + ((ViewUserDetailActivity) activity).deleteComment(commentData.getFullName()); + } + }); + } + + shareTextView.setOnClickListener(view -> { + dismiss(); + try { + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("text/plain"); + intent.putExtra(Intent.EXTRA_TEXT, commentData.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(); + } + }); + + copyTextView.setOnClickListener(view -> { + dismiss(); + CopyTextBottomSheetFragment copyTextBottomSheetFragment = new CopyTextBottomSheetFragment(); + Bundle copyBundle = new Bundle(); + copyBundle.putString(CopyTextBottomSheetFragment.EXTRA_MARKDOWN, commentData.getCommentMarkdown()); + copyBundle.putString(CopyTextBottomSheetFragment.EXTRA_RAW_TEXT, commentData.getCommentRawText()); + copyTextBottomSheetFragment.setArguments(copyBundle); + copyTextBottomSheetFragment.show(activity.getSupportFragmentManager(), copyTextBottomSheetFragment.getTag()); + }); + + return rootView; + } + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + activity = (AppCompatActivity) context; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/ModifyCommentBottomSheetFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/ModifyCommentBottomSheetFragment.java deleted file mode 100644 index b0c43ffd..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/ModifyCommentBottomSheetFragment.java +++ /dev/null @@ -1,88 +0,0 @@ -package ml.docilealligator.infinityforreddit.Fragment; - - -import android.app.Activity; -import android.content.Intent; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.fragment.app.Fragment; - -import com.deishelon.roundedbottomsheet.RoundedBottomSheetDialogFragment; - -import butterknife.BindView; -import butterknife.ButterKnife; -import ml.docilealligator.infinityforreddit.Activity.EditCommentActivity; -import ml.docilealligator.infinityforreddit.Activity.ViewPostDetailActivity; -import ml.docilealligator.infinityforreddit.Activity.ViewUserDetailActivity; -import ml.docilealligator.infinityforreddit.R; - - -/** - * A simple {@link Fragment} subclass. - */ -public class ModifyCommentBottomSheetFragment extends RoundedBottomSheetDialogFragment { - - public static final String EXTRA_COMMENT_FULLNAME = "ECF"; - public static final String EXTRA_COMMENT_CONTENT = "ECC"; - public static final String EXTRA_ACCESS_TOKEN = "EAT"; - public static final String EXTRA_POSITION = "EP"; - @BindView(R.id.edit_text_view_modify_comment_bottom_sheet_fragment) - TextView editTextView; - @BindView(R.id.delete_text_view_modify_comment_bottom_sheet_fragment) - TextView deleteTextView; - public ModifyCommentBottomSheetFragment() { - // Required empty public constructor - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_modify_comment_bottom_sheet, container, false); - ButterKnife.bind(this, rootView); - - Activity activity = getActivity(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O - && (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { - rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); - } - - Bundle bundle = getArguments(); - String fullName = bundle.getString(EXTRA_COMMENT_FULLNAME); - String content = bundle.getString(EXTRA_COMMENT_CONTENT); - String accessToken = bundle.getString(EXTRA_ACCESS_TOKEN); - - editTextView.setOnClickListener(view -> { - Intent intent = new Intent(activity, EditCommentActivity.class); - intent.putExtra(EditCommentActivity.EXTRA_ACCESS_TOKEN, accessToken); - intent.putExtra(EditCommentActivity.EXTRA_FULLNAME, fullName); - intent.putExtra(EditCommentActivity.EXTRA_CONTENT, content); - intent.putExtra(EditCommentActivity.EXTRA_POSITION, bundle.getInt(EXTRA_POSITION)); - if (activity instanceof ViewPostDetailActivity) { - activity.startActivityForResult(intent, ViewPostDetailActivity.EDIT_COMMENT_REQUEST_CODE); - } else { - startActivity(intent); - } - - dismiss(); - }); - - deleteTextView.setOnClickListener(view -> { - dismiss(); - if (activity instanceof ViewPostDetailActivity) { - ((ViewPostDetailActivity) activity).deleteComment(fullName, bundle.getInt(EXTRA_POSITION)); - } else if (activity instanceof ViewUserDetailActivity) { - ((ViewUserDetailActivity) activity).deleteComment(fullName); - } - }); - - return rootView; - } - -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java index c7cb5734..d5c86143 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseComment.java @@ -127,10 +127,12 @@ public class ParseComment { String parentId = singleCommentData.getString(JSONUtils.PARENT_ID_KEY); boolean isSubmitter = singleCommentData.getBoolean(JSONUtils.IS_SUBMITTER_KEY); String distinguished = singleCommentData.getString(JSONUtils.DISTINGUISHED_KEY); - String commentContent = ""; + String commentMarkdown = ""; if (!singleCommentData.isNull(JSONUtils.BODY_KEY)) { - commentContent = Utils.modifyMarkdown(singleCommentData.getString(JSONUtils.BODY_KEY).trim()); + 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(); int score = singleCommentData.getInt(JSONUtils.SCORE_KEY); int voteType; @@ -157,8 +159,9 @@ public class ParseComment { boolean hasReply = !(singleCommentData.get(JSONUtils.REPLIES_KEY) instanceof String); return new CommentData(id, fullName, author, authorFlair, linkAuthor, formattedSubmitTime, - submitTime, commentContent, linkId, subredditName, parentId, score, voteType, - isSubmitter, distinguished, permalink, depth, collapsed, hasReply, scoreHidden, saved); + submitTime, commentMarkdown, commentRawText, linkId, subredditName, parentId, score, + voteType, isSubmitter, distinguished, permalink, depth, collapsed, hasReply, + scoreHidden, saved); } @Nullable 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 91babc40..77338813 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/JSONUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/JSONUtils.java @@ -43,6 +43,7 @@ public class JSONUtils { public static final String REDDIT_VIDEO_PREVIEW_KEY = "reddit_video_preview"; public static final String STICKIED_KEY = "stickied"; public static final String BODY_KEY = "body"; + public static final String BODY_HTML_KEY = "body_html"; public static final String COLLAPSED_KEY = "collapsed"; public static final String IS_SUBMITTER_KEY = "is_submitter"; public static final String REPLIES_KEY = "replies"; diff --git a/app/src/main/res/drawable-night/ic_delete_24dp.xml b/app/src/main/res/drawable-night/ic_delete_24dp.xml new file mode 100644 index 00000000..4169cae5 --- /dev/null +++ b/app/src/main/res/drawable-night/ic_delete_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-night/ic_edit_24dp.xml b/app/src/main/res/drawable-night/ic_edit_24dp.xml new file mode 100644 index 00000000..7f32de65 --- /dev/null +++ b/app/src/main/res/drawable-night/ic_edit_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-night/ic_share_24dp.xml b/app/src/main/res/drawable-night/ic_share_24dp.xml new file mode 100644 index 00000000..cbe3d4aa --- /dev/null +++ b/app/src/main/res/drawable-night/ic_share_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_delete_24dp.xml b/app/src/main/res/drawable/ic_delete_24dp.xml new file mode 100644 index 00000000..aaf18eb9 --- /dev/null +++ b/app/src/main/res/drawable/ic_delete_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_edit_24dp.xml b/app/src/main/res/drawable/ic_edit_24dp.xml new file mode 100644 index 00000000..17a2a81f --- /dev/null +++ b/app/src/main/res/drawable/ic_edit_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_share_24dp.xml b/app/src/main/res/drawable/ic_share_24dp.xml new file mode 100644 index 00000000..82ddcec3 --- /dev/null +++ b/app/src/main/res/drawable/ic_share_24dp.xml @@ -0,0 +1,9 @@ + + + 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 new file mode 100644 index 00000000..397d8439 --- /dev/null +++ b/app/src/main/res/layout/fragment_comment_more_bottom_sheet.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_modify_comment_bottom_sheet.xml b/app/src/main/res/layout/fragment_modify_comment_bottom_sheet.xml deleted file mode 100644 index 4bc3c547..00000000 --- a/app/src/main/res/layout/fragment_modify_comment_bottom_sheet.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_comment.xml b/app/src/main/res/layout/item_comment.xml index faf11a07..c303efaa 100644 --- a/app/src/main/res/layout/item_comment.xml +++ b/app/src/main/res/layout/item_comment.xml @@ -154,7 +154,6 @@ android:clickable="true" android:focusable="true" android:src="@drawable/ic_more_vert_grey_24dp" - android:visibility="gone" app:layout_constraintEnd_toStartOf="@+id/expand_button_item_post_comment" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent"/> @@ -198,11 +197,11 @@ android:clickable="true" android:focusable="true" android:src="@drawable/ic_reply_grey_24dp" - app:layout_constraintEnd_toStartOf="@id/share_button_item_post_comment" + app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent"/> - + app:layout_constraintBottom_toBottomOf="parent"/>--> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2b7e673b..44e93567 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -411,4 +411,7 @@ Copy Raw Text Copy All Markdown Copy All Raw Text + + Save comment + Unsave comment -- cgit v1.2.3