diff --git a/WordPress/src/main/java/org/wordpress/android/ui/comments/CommentDetailFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/comments/CommentDetailFragment.java index 7d9856428fcc..e0402ce91640 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/comments/CommentDetailFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/comments/CommentDetailFragment.java @@ -14,6 +14,7 @@ import androidx.core.content.res.ResourcesCompat; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; +import androidx.lifecycle.ViewModelProvider; import com.gravatar.AvatarQueryOptions; import com.gravatar.AvatarUrl; @@ -138,6 +139,8 @@ public abstract class CommentDetailFragment extends ViewPagerFragment implements @Nullable protected CommentDetailFragmentBinding mBinding = null; + private CommentDetailViewModel mViewModel; + private final OnActionClickListener mOnActionClickListener = new OnActionClickListener() { @Override public void onEditCommentClicked() { editComment(); @@ -168,7 +171,7 @@ public abstract class CommentDetailFragment extends ViewPagerFragment implements public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ((WordPress) requireActivity().getApplication()).component().inject(this); - + mViewModel = new ViewModelProvider(this).get(CommentDetailViewModel.class); mCommentSource = (CommentSource) requireArguments().getSerializable(KEY_MODE); setHasOptionsMenu(true); } @@ -655,7 +658,7 @@ private void trackModerationEvent(final CommentStatus newStatus) { /* * approve, disapprove, spam, or trash the current comment */ - private void moderateComment( + protected void moderateComment( @NonNull SiteModel site, @NonNull CommentModel comment, @Nullable Note note, @@ -687,7 +690,7 @@ private void moderateComment( // Fire the appropriate listener if we have one if (note != null && mOnNoteCommentActionListener != null) { mOnNoteCommentActionListener.onModerateCommentForNote(note, newStatus); - dispatchModerationAction(site, comment, newStatus); + mViewModel.dispatchModerationAction(site, comment, newStatus); } else if (mOnCommentActionListener != null) { mOnCommentActionListener.onModerateComment(comment, newStatus); // Sad, but onModerateComment does the moderation itself (due to the undo bar), this should be refactored, @@ -695,25 +698,6 @@ private void moderateComment( } } - private void dispatchModerationAction( - @NonNull SiteModel site, - @NonNull CommentModel comment, - CommentStatus newStatus - ) { - if (newStatus == CommentStatus.DELETED) { - // For deletion, we need to dispatch a specific action. - mCommentsStoreAdapter.dispatch( - CommentActionBuilder.newDeleteCommentAction(new RemoteCommentPayload(site, comment)) - ); - } else { - // Actual moderation (push the modified comment). - comment.setStatus(newStatus.toString()); - mCommentsStoreAdapter.dispatch( - CommentActionBuilder.newPushCommentAction(new RemoteCommentPayload(site, comment)) - ); - } - } - /* * display the comment associated with the passed notification */ diff --git a/WordPress/src/main/java/org/wordpress/android/ui/comments/CommentDetailViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/comments/CommentDetailViewModel.kt index 4fd4ad0d4de0..70d5c45b04e8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/comments/CommentDetailViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/comments/CommentDetailViewModel.kt @@ -57,15 +57,21 @@ class CommentDetailViewModel @Inject constructor( } /** - * Dispatch a moderation action to the server, it does not include [CommentStatus.DELETED] status + * Dispatch a moderation action to the server */ fun dispatchModerationAction(site: SiteModel, comment: CommentModel, status: CommentStatus) { + comment.apply { this.status = status.toString() } commentsStoreAdapter.dispatch( - CommentActionBuilder.newPushCommentAction(CommentStore.RemoteCommentPayload(site, comment)) + if (status == CommentStatus.DELETED) { + // For deletion, we need to dispatch a specific action. + CommentActionBuilder.newDeleteCommentAction(CommentStore.RemoteCommentPayload(site, comment)) + } else { + // Actual moderation (push the modified comment). + CommentActionBuilder.newPushCommentAction(CommentStore.RemoteCommentPayload(site, comment)) + } ) - comment.apply { this.status = status.toString() } - .let { _updatedComment.postValue(it) } + _updatedComment.postValue(comment) } /** diff --git a/WordPress/src/main/java/org/wordpress/android/ui/comments/SharedCommentDetailFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/comments/SharedCommentDetailFragment.kt index 4e6e61b5c192..219e737399ce 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/comments/SharedCommentDetailFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/comments/SharedCommentDetailFragment.kt @@ -8,6 +8,7 @@ import android.widget.TextView import androidx.core.content.ContextCompat import androidx.core.view.isVisible import androidx.fragment.app.viewModels +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.gravatar.AvatarQueryOptions import com.gravatar.AvatarUrl import com.gravatar.types.Email @@ -16,6 +17,7 @@ import org.wordpress.android.R import org.wordpress.android.analytics.AnalyticsTracker import org.wordpress.android.databinding.CommentApprovedBinding import org.wordpress.android.databinding.CommentPendingBinding +import org.wordpress.android.databinding.CommentTrashBinding import org.wordpress.android.fluxc.model.CommentModel import org.wordpress.android.fluxc.model.CommentStatus import org.wordpress.android.fluxc.model.SiteModel @@ -79,29 +81,45 @@ abstract class SharedCommentDetailFragment : CommentDetailFragment() { // reset visibilities mBinding?.layoutCommentPending?.root?.isVisible = false mBinding?.layoutCommentApproved?.root?.isVisible = false + mBinding?.layoutCommentTrash?.root?.isVisible = false val commentStatus = CommentStatus.fromString(comment.status) when (commentStatus) { CommentStatus.APPROVED -> mBinding?.layoutCommentApproved?.bindApprovedView() CommentStatus.UNAPPROVED -> mBinding?.layoutCommentPending?.bindPendingView() - CommentStatus.SPAM -> {} - CommentStatus.TRASH -> {} - CommentStatus.DELETED -> {} - CommentStatus.ALL -> {} - CommentStatus.UNREPLIED -> {} - CommentStatus.UNSPAM -> {} - CommentStatus.UNTRASH -> {} + CommentStatus.SPAM, CommentStatus.TRASH -> mBinding?.layoutCommentTrash?.bindTrashView() + CommentStatus.DELETED, + CommentStatus.ALL, + CommentStatus.UNREPLIED, + CommentStatus.UNSPAM, + CommentStatus.UNTRASH -> { + // do nothing + } } } + private fun CommentTrashBinding.bindTrashView() { + root.isVisible = true + buttonDeleteComment.setOnClickListener { + showDeleteCommentDialog() + } + } + + private fun showDeleteCommentDialog() { + MaterialAlertDialogBuilder(requireContext()) + .setTitle(R.string.delete) + .setMessage(R.string.dlg_sure_to_delete_comment) + .setPositiveButton(R.string.yes) { _, _ -> + moderateComment(site, comment, mNote, CommentStatus.DELETED) + } + .setNegativeButton(R.string.no) { _, _ -> } + .show() + } + private fun CommentPendingBinding.bindPendingView() { root.isVisible = true buttonApproveComment.setOnClickListener { - viewModel.dispatchModerationAction( - site, - comment, - CommentStatus.APPROVED - ) + moderateComment(site, comment, mNote, CommentStatus.APPROVED) } textMoreOptions.setOnClickListener { showModerationBottomSheet() } } @@ -168,7 +186,10 @@ abstract class SharedCommentDetailFragment : CommentDetailFragment() { canTrash = enabledActions.canTrash(), ) ).apply { - onApprovedClicked = { viewModel.dispatchModerationAction(site, comment, CommentStatus.APPROVED) } + onApprovedClicked = { moderateComment(site, comment, mNote, CommentStatus.APPROVED) } + onPendingClicked = { moderateComment(site, comment, mNote, CommentStatus.UNAPPROVED) } + onTrashClicked = { moderateComment(site, comment, mNote, CommentStatus.TRASH) } + onSpamClicked = { moderateComment(site, comment, mNote, CommentStatus.SPAM) } }.show(childFragmentManager, ModerationBottomSheetDialogFragment.TAG) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsDetailActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsDetailActivity.java index 8cc91abeb3e2..c95c62b91051 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsDetailActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsDetailActivity.java @@ -568,7 +568,10 @@ public void onModerateCommentForNote(@NonNull Note note, @NonNull CommentStatus resultIntent.putExtra(NotificationsListFragment.NOTE_MODERATE_STATUS_EXTRA, newStatus.toString()); setResult(RESULT_OK, resultIntent); - finish(); + + if (newStatus == CommentStatus.DELETED) { + finish(); + } } @SuppressWarnings("unused") diff --git a/WordPress/src/main/res/drawable/trash_24.xml b/WordPress/src/main/res/drawable/trash_24.xml new file mode 100644 index 000000000000..1608306c67d6 --- /dev/null +++ b/WordPress/src/main/res/drawable/trash_24.xml @@ -0,0 +1,9 @@ + + + diff --git a/WordPress/src/main/res/layout/comment_detail_fragment.xml b/WordPress/src/main/res/layout/comment_detail_fragment.xml index 282733f2f9ab..e26ec29c670f 100644 --- a/WordPress/src/main/res/layout/comment_detail_fragment.xml +++ b/WordPress/src/main/res/layout/comment_detail_fragment.xml @@ -31,6 +31,13 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="gone"/> + + + + + + + + + + diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index c3eb0cd2d39e..2a3f1524f47d 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -465,8 +465,10 @@ Change status Comment pending moderation + Comment in Trash Comment Approved Approve comment + Delete permanently More options Choose status Approved