package kr.kdev.dg1s.biowiki.ui.comments;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Html;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.TextView;
import com.android.volley.VolleyError;
import com.wordpress.rest.RestRequest;
import org.json.JSONObject;
import java.util.EnumSet;
import kr.kdev.dg1s.biowiki.BioWiki;
import kr.kdev.dg1s.biowiki.Constants;
import kr.kdev.dg1s.biowiki.R;
import kr.kdev.dg1s.biowiki.datasets.CommentTable;
import kr.kdev.dg1s.biowiki.models.Comment;
import kr.kdev.dg1s.biowiki.models.CommentStatus;
import kr.kdev.dg1s.biowiki.models.Note;
import kr.kdev.dg1s.biowiki.models.Note.EnabledActions;
import kr.kdev.dg1s.biowiki.ui.comments.CommentActions.ChangeType;
import kr.kdev.dg1s.biowiki.ui.comments.CommentActions.ChangedFrom;
import kr.kdev.dg1s.biowiki.ui.comments.CommentActions.OnCommentChangeListener;
import kr.kdev.dg1s.biowiki.ui.notifications.NotificationFragment;
import kr.kdev.dg1s.biowiki.util.AniUtils;
import kr.kdev.dg1s.biowiki.util.AppLog;
import kr.kdev.dg1s.biowiki.util.BWLinkMovementMethod;
import kr.kdev.dg1s.biowiki.util.DateTimeUtils;
import kr.kdev.dg1s.biowiki.util.EditTextUtils;
import kr.kdev.dg1s.biowiki.util.GravatarUtils;
import kr.kdev.dg1s.biowiki.util.HtmlUtils;
import kr.kdev.dg1s.biowiki.util.NetworkUtils;
import kr.kdev.dg1s.biowiki.util.PhotonUtils;
import kr.kdev.dg1s.biowiki.util.ToastUtils;
import kr.kdev.dg1s.biowiki.util.VolleyUtils;
import kr.kdev.dg1s.biowiki.widgets.BWNetworkImageView;
/**
* Created by nbradbury on 11/11/13.
* comment detail displayed from both the notification list and the comment list
* prior to this there were separate comment detail screens for each list
*/
public class CommentDetailFragment extends Fragment implements NotificationFragment {
private static final String KEY_LOCAL_BLOG_ID = "local_blog_id";
private static final String KEY_COMMENT_ID = "comment_id";
private int mLocalBlogId;
private int mRemoteBlogId;
private Comment mComment;
private Note mNote;
private TextView mTxtStatus;
private TextView mTxtContent;
private ImageView mImgSubmitReply;
private EditText mEditReply;
private ViewGroup mLayoutReply;
private ViewGroup mLayoutButtons;
private TextView mBtnModerateComment;
private TextView mBtnSpamComment;
private TextView mBtnEditComment;
private TextView mBtnTrashComment;
private boolean mIsSubmittingReply = false;
private boolean mIsModeratingComment = false;
private boolean mIsRequestingComment = false;
private boolean mIsUsersBlog = false;
private OnCommentChangeListener mOnCommentChangeListener;
private OnPostClickListener mOnPostClickListener;
/*
* these determine which actions (moderation, replying, marking as spam) to enable
* for this comment - all actions are enabled when opened from the comment list, only
* changed when opened from a notification
*/
private EnumSet<EnabledActions> mEnabledActions = EnumSet.allOf(EnabledActions.class);
/*
* used when called from comment list
*/
static CommentDetailFragment newInstance(int localBlogId, long commentId) {
CommentDetailFragment fragment = new CommentDetailFragment();
fragment.setComment(localBlogId, commentId);
return fragment;
}
/*
* used when called from notification list for a comment notification
*/
public static CommentDetailFragment newInstance(final Note note) {
CommentDetailFragment fragment = new CommentDetailFragment();
fragment.setNote(note);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
int localBlogId = savedInstanceState.getInt(KEY_LOCAL_BLOG_ID);
long commentId = savedInstanceState.getLong(KEY_COMMENT_ID);
setComment(localBlogId, commentId);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (hasComment()) {
outState.putInt(KEY_LOCAL_BLOG_ID, getLocalBlogId());
outState.putLong(KEY_COMMENT_ID, getCommentId());
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.comment_detail_fragment, container, false);
mTxtStatus = (TextView) view.findViewById(R.id.text_status);
mTxtContent = (TextView) view.findViewById(R.id.text_content);
mLayoutButtons = (ViewGroup) view.findViewById(R.id.layout_buttons);
mBtnModerateComment = (TextView) mLayoutButtons.findViewById(R.id.text_btn_moderate);
mBtnSpamComment = (TextView) mLayoutButtons.findViewById(R.id.text_btn_spam);
mBtnEditComment = (TextView) mLayoutButtons.findViewById(R.id.image_edit_comment);
mBtnTrashComment = (TextView) mLayoutButtons.findViewById(R.id.image_trash_comment);
setTextDrawable(mBtnSpamComment, R.drawable.ic_cab_spam);
setTextDrawable(mBtnEditComment, R.drawable.ab_icon_edit);
setTextDrawable(mBtnTrashComment, R.drawable.ic_cab_trash);
mLayoutReply = (ViewGroup) view.findViewById(R.id.layout_comment_box);
mEditReply = (EditText) mLayoutReply.findViewById(R.id.edit_comment);
mImgSubmitReply = (ImageView) mLayoutReply.findViewById(R.id.image_post_comment);
// hide moderation buttons until updateModerationButtons() is called
mLayoutButtons.setVisibility(View.GONE);
mBtnEditComment.setVisibility(View.GONE);
// this is necessary in order for anchor tags in the comment text to be clickable
mTxtContent.setLinksClickable(true);
mTxtContent.setMovementMethod(BWLinkMovementMethod.getInstance());
mEditReply.setHint(R.string.reader_hint_comment_on_comment);
mEditReply.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_ACTION_SEND)
submitReply();
return false;
}
});
mImgSubmitReply.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
submitReply();
}
});
mBtnSpamComment.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mComment.getStatusEnum() == CommentStatus.SPAM) {
moderateComment(CommentStatus.APPROVED);
} else {
moderateComment(CommentStatus.SPAM);
}
}
});
mBtnEditComment.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
editComment();
}
});
mBtnTrashComment.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
confirmDeleteComment();
}
});
return view;
}
void setComment(int localBlogId, long commentId) {
setComment(localBlogId, CommentTable.getComment(localBlogId, commentId));
}
private void setComment(int localBlogId, final Comment comment) {
mComment = comment;
mLocalBlogId = localBlogId;
// is this comment on one of the user's blogs? it won't be if this was displayed from a
// notification about a reply to a comment this user posted on someone else's blog
mIsUsersBlog = (comment != null && BioWiki.wpDB.isLocalBlogIdInDatabase(mLocalBlogId));
if (mIsUsersBlog)
mRemoteBlogId = BioWiki.wpDB.getRemoteBlogIdForLocalTableBlogId(mLocalBlogId);
if (hasActivity())
showComment();
}
@Override
public Note getNote() {
return mNote;
}
@Override
public void setNote(Note note) {
mNote = note;
if (hasActivity() && mNote != null)
showComment();
}
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof OnCommentChangeListener)
mOnCommentChangeListener = (OnCommentChangeListener) activity;
if (activity instanceof OnPostClickListener)
mOnPostClickListener = (OnPostClickListener) activity;
}
@Override
public void onStart() {
super.onStart();
showComment();
}
@Override
public void onPause() {
super.onPause();
EditTextUtils.hideSoftInput(mEditReply);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == Constants.INTENT_COMMENT_EDITOR && resultCode == Activity.RESULT_OK) {
reloadComment();
// tell the host to reload the comment list
if (mOnCommentChangeListener != null)
mOnCommentChangeListener.onCommentChanged(ChangedFrom.COMMENT_DETAIL, ChangeType.EDITED);
}
}
private boolean hasActivity() {
return (getActivity() != null && !isRemoving());
}
private boolean hasComment() {
return (mComment != null);
}
long getCommentId() {
return (mComment != null ? mComment.commentID : 0);
}
private int getLocalBlogId() {
return mLocalBlogId;
}
private int getRemoteBlogId() {
return mRemoteBlogId;
}
/*
* reload the current comment from the local database
*/
void reloadComment() {
if (!hasComment())
return;
Comment updatedComment = CommentTable.getComment(mLocalBlogId, getCommentId());
setComment(mLocalBlogId, updatedComment);
}
/*
* resets to no comment
*/
void clear() {
setNote(null);
setComment(0, null);
}
/*
* open the comment for editing
*/
private void editComment() {
if (!hasActivity() || !hasComment())
return;
// IMPORTANT: don't use getActivity().startActivityForResult() or else onActivityResult()
// won't be called in this fragment
// https://code.google.com/p/android/issues/detail?id=15394#c45
Intent intent = new Intent(getActivity(), EditCommentActivity.class);
intent.putExtra(EditCommentActivity.ARG_LOCAL_BLOG_ID, getLocalBlogId());
intent.putExtra(EditCommentActivity.ARG_COMMENT_ID, getCommentId());
startActivityForResult(intent, Constants.INTENT_COMMENT_EDITOR);
}
/*
* display the current comment
*/
private void showComment() {
if (!hasActivity() || getView() == null)
return;
// these two views contain all the other views except the progress bar
final ScrollView scrollView = (ScrollView) getView().findViewById(R.id.scroll_view);
final View layoutBottom = getView().findViewById(R.id.layout_bottom);
// hide container views when comment is null (will happen when opened from a notification)
if (mComment == null) {
scrollView.setVisibility(View.GONE);
layoutBottom.setVisibility(View.GONE);
// if a notification was passed, request its associated comment
if (mNote != null && !mIsRequestingComment)
showCommentForNote(mNote);
return;
}
scrollView.setVisibility(View.VISIBLE);
layoutBottom.setVisibility(View.VISIBLE);
final BWNetworkImageView imgAvatar = (BWNetworkImageView) getView().findViewById(R.id.image_avatar);
final TextView txtName = (TextView) getView().findViewById(R.id.text_name);
final TextView txtDate = (TextView) getView().findViewById(R.id.text_date);
txtName.setText(mComment.hasAuthorName() ? mComment.getAuthorName() : getString(R.string.anonymous));
txtDate.setText(DateTimeUtils.javaDateToTimeSpan(mComment.getDatePublished()));
int maxImageSz = getResources().getDimensionPixelSize(R.dimen.reader_comment_max_image_size);
CommentUtils.displayHtmlComment(mTxtContent, mComment.getCommentText(), maxImageSz);
int avatarSz = getResources().getDimensionPixelSize(R.dimen.avatar_sz_large);
if (mComment.hasProfileImageUrl()) {
imgAvatar.setImageUrl(PhotonUtils.fixAvatar(mComment.getProfileImageUrl(), avatarSz), BWNetworkImageView.ImageType.AVATAR);
} else if (mComment.hasAuthorEmail()) {
String avatarUrl = GravatarUtils.gravatarUrlFromEmail(mComment.getAuthorEmail(), avatarSz);
imgAvatar.setImageUrl(avatarUrl, BWNetworkImageView.ImageType.AVATAR);
} else {
imgAvatar.setImageUrl(null, BWNetworkImageView.ImageType.AVATAR);
}
updateStatusViews();
// navigate to author's home page when avatar or name clicked
if (mComment.hasAuthorUrl()) {
/*
View.OnClickListener authorListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
ReaderActivityLauncher.openUrl(getActivity(), mComment.getAuthorUrl());
}
};
imgAvatar.setOnClickListener(authorListener);
txtName.setOnClickListener(authorListener);
txtName.setTextColor(getResources().getColor(R.color.reader_hyperlink));
*/
} else {
txtName.setTextColor(getResources().getColor(R.color.grey_medium_dark));
}
showPostTitle(getRemoteBlogId(), mComment.postID);
// make sure reply box is showing
if (mLayoutReply.getVisibility() != View.VISIBLE && canReply())
AniUtils.flyIn(mLayoutReply);
}
/*
* displays the passed post title for the current comment, updates stored title if one doesn't exist
*/
private void setPostTitle(TextView txtTitle, String postTitle, boolean isHyperlink) {
if (txtTitle == null || !hasActivity())
return;
if (TextUtils.isEmpty(postTitle)) {
txtTitle.setText(R.string.untitled);
return;
}
// if comment doesn't have a post title, set it to the passed one and save to comment table
if (hasComment() && !mComment.hasPostTitle()) {
mComment.setPostTitle(postTitle);
CommentTable.updateCommentPostTitle(getLocalBlogId(), getCommentId(), postTitle);
}
// display "on [Post Title]..."
if (isHyperlink) {
String html = getString(R.string.on)
+ " <font color=" + HtmlUtils.colorResToHtmlColor(getActivity(), R.color.reader_hyperlink) + ">"
+ postTitle.trim()
+ "</font>";
txtTitle.setText(Html.fromHtml(html));
} else {
txtTitle.setText(getString(R.string.on) + " " + postTitle.trim());
}
}
/*
* ensure the post associated with this comment is available to the reader and show its
* title above the comment
*/
private void showPostTitle(final int blogId, final long postId) {
if (!hasActivity())
return;
final TextView txtPostTitle = (TextView) getView().findViewById(R.id.text_post_title);
boolean isDotComOrJetpack = BioWiki.wpDB.isRemoteBlogIdDotComOrJetpack(mRemoteBlogId);
final String title;
final boolean hasTitle;
if (mComment.hasPostTitle()) {
// use comment's stored post title if available
title = mComment.getPostTitle();
hasTitle = true;
} else {
title = null;
hasTitle = false;
}
if (hasTitle) {
setPostTitle(txtPostTitle, title, isDotComOrJetpack);
} else {
txtPostTitle.setText(R.string.untitled);
}
// if this is a .com or jetpack blog, tapping the title shows the associated post
// in the reader
/*
if (isDotComOrJetpack) {
// first make sure this post is available to the reader, and once it's retrieved set
// the title if it wasn't set above
if (!postExists) {
AppLog.d(AppLog.T.COMMENTS, "comment detail > retrieving post");
ReaderPostActions.requestPost(blogId, postId, new ReaderActions.ActionListener() {
@Override
public void onActionResult(boolean succeeded) {
if (!hasActivity())
return;
// update title if it wasn't set above
if (!hasTitle) {
String postTitle = ReaderPostTable.getPostTitle(blogId, postId);
if (!TextUtils.isEmpty(postTitle)) {
setPostTitle(txtPostTitle, postTitle, true);
} else {
txtPostTitle.setText(R.string.untitled);
}
}
}
});
}
txtPostTitle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mOnPostClickListener != null) {
mOnPostClickListener.onPostClicked(getNote(), mRemoteBlogId, (int) mComment.postID);
} else {
// right now this will happen from notifications
AppLog.i(AppLog.T.COMMENTS, "comment detail > no post click listener");
ReaderActivityLauncher.showReaderPostDetail(getActivity(), mRemoteBlogId, mComment.postID);
}
}
});
}
*/
}
private void confirmDeleteComment() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.dlg_confirm_trash_comments);
builder.setTitle(R.string.trash);
builder.setCancelable(true);
builder.setPositiveButton(R.string.trash_yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
moderateComment(CommentStatus.TRASH);
}
});
builder.setNegativeButton(R.string.trash_no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
private void dismissDialog(int id) {
if (!hasActivity())
return;
try {
getActivity().dismissDialog(id);
} catch (IllegalArgumentException e) {
// raised when dialog wasn't created
}
}
/*
* approve, unapprove, spam, or trash the current comment
*/
private void moderateComment(final CommentStatus newStatus) {
if (!hasActivity() || !hasComment() || mIsModeratingComment)
return;
if (!NetworkUtils.checkConnection(getActivity()))
return;
// show dialog while moderating
final int dlgId;
switch (newStatus) {
case APPROVED:
dlgId = CommentDialogs.ID_COMMENT_DLG_APPROVING;
break;
case UNAPPROVED:
dlgId = CommentDialogs.ID_COMMENT_DLG_UNAPPROVING;
break;
case SPAM:
dlgId = CommentDialogs.ID_COMMENT_DLG_SPAMMING;
break;
case TRASH:
dlgId = CommentDialogs.ID_COMMENT_DLG_TRASHING;
break;
default:
return;
}
getActivity().showDialog(dlgId);
// disable buttons during request
mLayoutButtons.setEnabled(false);
// animate the buttons out (updateStatusViews will re-display them when request completes)
mLayoutButtons.clearAnimation();
AniUtils.flyOut(mLayoutButtons);
// hide status (updateStatusViews will un-hide it)
if (mTxtStatus.getVisibility() == View.VISIBLE) {
mTxtStatus.clearAnimation();
AniUtils.startAnimation(mTxtStatus, R.anim.fade_out);
mTxtStatus.setVisibility(View.INVISIBLE);
}
CommentActions.CommentActionListener actionListener = new CommentActions.CommentActionListener() {
@Override
public void onActionResult(boolean succeeded) {
mIsModeratingComment = false;
if (hasActivity()) {
dismissDialog(dlgId);
mLayoutButtons.setEnabled(true);
if (succeeded) {
mComment.setStatus(CommentStatus.toString(newStatus));
} else {
ToastUtils.showToast(getActivity(), R.string.error_moderate_comment, ToastUtils.Duration.LONG);
}
if (newStatus == CommentStatus.TRASH) {
// clear the comment if it was trashed
clear();
} else {
// reflect the new status - note this MUST come after mComment.setStatus
updateStatusViews();
}
}
if (succeeded && mOnCommentChangeListener != null) {
ChangeType changeType = (newStatus == CommentStatus.TRASH ? ChangeType.TRASHED : ChangeType.STATUS);
mOnCommentChangeListener.onCommentChanged(ChangedFrom.COMMENT_DETAIL, changeType);
}
}
};
mIsModeratingComment = true;
CommentActions.moderateComment(mLocalBlogId, mComment, newStatus, actionListener);
}
/*
* post comment box text as a reply to the current comment
*/
private void submitReply() {
if (!hasActivity() || mIsSubmittingReply)
return;
if (!NetworkUtils.checkConnection(getActivity()))
return;
final String replyText = EditTextUtils.getText(mEditReply);
if (TextUtils.isEmpty(replyText))
return;
// disable editor, hide soft keyboard, hide submit icon, and show progress spinner while submitting
mEditReply.setEnabled(false);
EditTextUtils.hideSoftInput(mEditReply);
mImgSubmitReply.setVisibility(View.GONE);
final ProgressBar progress = (ProgressBar) getView().findViewById(R.id.progress_submit_comment);
progress.setVisibility(View.VISIBLE);
// animate the buttons out (updateStatusViews will re-display them when request completes)
mLayoutButtons.clearAnimation();
AniUtils.flyOut(mLayoutButtons);
CommentActions.CommentActionListener actionListener = new CommentActions.CommentActionListener() {
@Override
public void onActionResult(boolean succeeded) {
mIsSubmittingReply = false;
if (succeeded && mOnCommentChangeListener != null)
mOnCommentChangeListener.onCommentChanged(ChangedFrom.COMMENT_DETAIL, ChangeType.REPLIED);
if (hasActivity()) {
mEditReply.setEnabled(true);
mImgSubmitReply.setVisibility(View.VISIBLE);
progress.setVisibility(View.GONE);
updateStatusViews();
if (succeeded) {
ToastUtils.showToast(getActivity(), getString(R.string.note_reply_successful));
mEditReply.setText(null);
} else {
ToastUtils.showToast(getActivity(), R.string.reply_failed, ToastUtils.Duration.LONG);
// refocus editor on failure and show soft keyboard
mEditReply.requestFocus();
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(mEditReply, InputMethodManager.SHOW_IMPLICIT);
}
}
}
};
mIsSubmittingReply = true;
if (mNote != null) {
CommentActions.submitReplyToCommentNote(mNote, replyText, actionListener);
} else {
CommentActions.submitReplyToComment(mLocalBlogId, mComment, replyText, actionListener);
}
}
/*
* sets the drawable for moderation buttons
*/
private void setTextDrawable(final TextView view, int resId) {
view.setCompoundDrawablesWithIntrinsicBounds(null, getResources().getDrawable(resId), null, null);
}
/*
* update the text, drawable & click listener for mBtnModerate based on
* the current status of the comment, show mBtnSpam if the comment isn't
* already marked as spam, and show the current status of the comment
*/
private void updateStatusViews() {
if (!hasActivity() || !hasComment())
return;
final int moderationDrawResId; // drawable resource id for moderation button
final int moderationTextResId; // string resource id for moderation button
final CommentStatus newStatus; // status to apply when moderation button is tapped
final int statusTextResId; // string resource id for status text
final int statusColor; // color for status text
switch (mComment.getStatusEnum()) {
case APPROVED:
moderationDrawResId = R.drawable.ic_cab_unapprove;
moderationTextResId = R.string.mnu_comment_unapprove;
newStatus = CommentStatus.UNAPPROVED;
statusTextResId = R.string.comment_status_approved;
statusColor = getActivity().getResources().getColor(R.color.comment_status_approved);
break;
case UNAPPROVED:
moderationDrawResId = R.drawable.ic_cab_approve;
moderationTextResId = R.string.mnu_comment_approve;
newStatus = CommentStatus.APPROVED;
statusTextResId = R.string.comment_status_unapproved;
statusColor = getActivity().getResources().getColor(R.color.comment_status_unapproved);
break;
case SPAM:
moderationDrawResId = R.drawable.ic_cab_approve;
moderationTextResId = R.string.mnu_comment_approve;
newStatus = CommentStatus.APPROVED;
statusTextResId = R.string.comment_status_spam;
statusColor = getActivity().getResources().getColor(R.color.comment_status_spam);
break;
case TRASH:
// should never get here
moderationDrawResId = R.drawable.ic_cab_approve;
moderationTextResId = R.string.mnu_comment_approve;
newStatus = CommentStatus.APPROVED;
statusTextResId = R.string.comment_status_trash;
statusColor = getActivity().getResources().getColor(R.color.comment_status_spam);
break;
default:
return;
}
// comment status is only shown if this comment is from one of this user's blogs and the
// comment hasn't been approved
if (mIsUsersBlog && mComment.getStatusEnum() != CommentStatus.APPROVED) {
mTxtStatus.setText(getString(statusTextResId).toUpperCase());
mTxtStatus.setTextColor(statusColor);
if (mTxtStatus.getVisibility() != View.VISIBLE) {
mTxtStatus.clearAnimation();
AniUtils.fadeIn(mTxtStatus);
}
} else {
mTxtStatus.setVisibility(View.GONE);
}
if (canModerate()) {
setTextDrawable(mBtnModerateComment, moderationDrawResId);
mBtnModerateComment.setText(moderationTextResId);
mBtnModerateComment.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
moderateComment(newStatus);
}
});
mBtnModerateComment.setVisibility(View.VISIBLE);
} else {
mBtnModerateComment.setVisibility(View.GONE);
}
if (canMarkAsSpam()) {
mBtnSpamComment.setVisibility(View.VISIBLE);
if (mComment.getStatusEnum() == CommentStatus.SPAM) {
mBtnSpamComment.setText(R.string.mnu_comment_unspam);
} else {
mBtnSpamComment.setText(R.string.mnu_comment_spam);
}
} else {
mBtnSpamComment.setVisibility(View.GONE);
}
mBtnTrashComment.setVisibility(canTrash() ? View.VISIBLE : View.GONE);
mBtnEditComment.setVisibility(canEdit() ? View.VISIBLE : View.GONE);
// animate the buttons in if they're not visible
if (mLayoutButtons.getVisibility() != View.VISIBLE && (canMarkAsSpam() || canModerate())) {
mLayoutButtons.clearAnimation();
AniUtils.flyIn(mLayoutButtons);
}
}
/*
* does user have permission to moderate/reply/spam this comment?
*/
private boolean canModerate() {
if (mEnabledActions == null)
return false;
return (mEnabledActions.contains(EnabledActions.ACTION_APPROVE)
|| mEnabledActions.contains(EnabledActions.ACTION_UNAPPROVE));
}
private boolean canMarkAsSpam() {
return (mEnabledActions != null && mEnabledActions.contains(EnabledActions.ACTION_SPAM));
}
private boolean canReply() {
return (mEnabledActions != null && mEnabledActions.contains(EnabledActions.ACTION_REPLY));
}
private boolean canTrash() {
return canModerate();
}
private boolean canEdit() {
return canModerate();
}
/*
* display the comment associated with the passed notification
*/
private void showCommentForNote(Note note) {
/*
* determine which actions to enable for this comment - if the comment is from this user's
* blog then all actions will be enabled, but they won't be if it's a reply to a comment
* this user made on someone else's blog
*/
mEnabledActions = note.getEnabledActions();
mRemoteBlogId = note.getBlogId();
long commentId = note.getCommentId();
// note that the local blog id won't be found if the comment is from someone else's blog
int localBlogId = BioWiki.wpDB.getLocalTableBlogIdForRemoteBlogId(mRemoteBlogId);
// first try to get from local db, if that fails request it from the server
final Comment comment = (localBlogId > 0 ? CommentTable.getComment(localBlogId, commentId) : null);
if (comment != null) {
setComment(localBlogId, comment);
} else {
requestComment(localBlogId, mRemoteBlogId, commentId);
}
}
/*
* request a comment - note that this uses the REST API rather than XMLRPC, which means the user must
* either be wp.com or have Jetpack, but it's safe to do this since this method is only called when
* displayed from a notification (and notifications require wp.com/Jetpack)
*/
private void requestComment(final int localBlogId,
final int remoteBlogId,
final long commentId) {
final ProgressBar progress = (hasActivity() ? (ProgressBar) getView().findViewById(R.id.progress_loading) : null);
if (progress != null)
progress.setVisibility(View.VISIBLE);
RestRequest.Listener restListener = new RestRequest.Listener() {
@Override
public void onResponse(JSONObject jsonObject) {
mIsRequestingComment = false;
if (hasActivity()) {
if (progress != null)
progress.setVisibility(View.GONE);
Comment comment = Comment.fromJSON(jsonObject);
if (comment != null) {
// save comment to local db if localBlogId is valid
if (localBlogId > 0)
CommentTable.addComment(localBlogId, comment);
// now, at long last, show the comment
setComment(localBlogId, comment);
}
}
}
};
RestRequest.ErrorListener restErrListener = new RestRequest.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
mIsRequestingComment = false;
AppLog.e(AppLog.T.COMMENTS, VolleyUtils.errStringFromVolleyError(volleyError), volleyError);
if (hasActivity()) {
if (progress != null)
progress.setVisibility(View.GONE);
ToastUtils.showToast(getActivity(), R.string.reader_toast_err_get_comment, ToastUtils.Duration.LONG);
}
}
};
final String path = String.format("/sites/%s/comments/%s", remoteBlogId, commentId);
mIsRequestingComment = true;
BioWiki.getRestClientUtils().get(path, restListener, restErrListener);
}
}