/*******************************************************************************
* This file is part of RedReader.
*
* RedReader is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RedReader is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RedReader. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package org.quantumbadger.redreader.views;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.quantumbadger.redreader.R;
import org.quantumbadger.redreader.account.RedditAccountManager;
import org.quantumbadger.redreader.common.General;
import org.quantumbadger.redreader.common.PrefsUtility;
import org.quantumbadger.redreader.common.RRThemeAttributes;
import org.quantumbadger.redreader.fragments.CommentListingFragment;
import org.quantumbadger.redreader.reddit.RedditCommentListItem;
import org.quantumbadger.redreader.reddit.api.RedditAPICommentAction;
import org.quantumbadger.redreader.reddit.prepared.RedditChangeDataManager;
import org.quantumbadger.redreader.reddit.prepared.RedditParsedComment;
import org.quantumbadger.redreader.reddit.prepared.RedditRenderableComment;
public class RedditCommentView extends FlingableItemView implements RedditChangeDataManager.Listener{
private static final Handler HANDLER = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case HANDLER_REQUEST_COMMENT_CHANGED: {
final RedditCommentView rcv = (RedditCommentView) msg.obj;
rcv.update();
break;
}
default:
throw new RuntimeException("Unknown message type " + msg.what);
}
}
};
private static final int HANDLER_REQUEST_COMMENT_CHANGED = 1;
private RedditCommentListItem mComment;
private final AppCompatActivity mActivity;
private final RedditChangeDataManager mChangeDataManager;
private final RRThemeAttributes mTheme;
private final TextView mHeader;
private final FrameLayout mBodyHolder;
private final IndentView mIndentView;
private final LinearLayout mIndentedContent;
private final float mFontScale;
private final boolean mShowLinkButtons;
private final CommentListener mListener;
@Nullable
private final CommentListingFragment mFragment;
@Nullable private ActionDescriptionPair mLeftFlingAction;
@Nullable private ActionDescriptionPair mRightFlingAction;
@Override
protected void onSetItemFlingPosition(final float position) {
mIndentedContent.setTranslationX(position);
}
private final class ActionDescriptionPair {
public final RedditAPICommentAction.RedditCommentAction action;
public final int descriptionRes;
private ActionDescriptionPair(RedditAPICommentAction.RedditCommentAction action, int descriptionRes) {
this.action = action;
this.descriptionRes = descriptionRes;
}
}
@Nullable
private ActionDescriptionPair chooseFlingAction(final PrefsUtility.CommentFlingAction pref) {
if(!mComment.isComment()) {
return null;
}
final RedditParsedComment comment = mComment.asComment().getParsedComment();
switch(pref) {
case UPVOTE:
if(mChangeDataManager.isUpvoted(comment)) {
return new ActionDescriptionPair(
RedditAPICommentAction.RedditCommentAction.UNVOTE,
R.string.action_vote_remove);
} else {
return new ActionDescriptionPair(
RedditAPICommentAction.RedditCommentAction.UPVOTE,
R.string.action_upvote);
}
case DOWNVOTE:
if(mChangeDataManager.isDownvoted(comment)) {
return new ActionDescriptionPair(
RedditAPICommentAction.RedditCommentAction.UNVOTE,
R.string.action_vote_remove);
} else {
return new ActionDescriptionPair(
RedditAPICommentAction.RedditCommentAction.DOWNVOTE,
R.string.action_downvote);
}
case SAVE:
if(mChangeDataManager.isSaved(comment)) {
return new ActionDescriptionPair(
RedditAPICommentAction.RedditCommentAction.UNSAVE,
R.string.action_unsave);
} else {
return new ActionDescriptionPair(
RedditAPICommentAction.RedditCommentAction.SAVE,
R.string.action_save);
}
case REPLY:
return new ActionDescriptionPair(
RedditAPICommentAction.RedditCommentAction.REPLY,
R.string.action_reply);
case USER_PROFILE:
return new ActionDescriptionPair(
RedditAPICommentAction.RedditCommentAction.USER_PROFILE,
R.string.action_user_profile);
case COLLAPSE:
if(mFragment == null) {
return null;
}
return new ActionDescriptionPair(
RedditAPICommentAction.RedditCommentAction.COLLAPSE,
R.string.action_collapse);
case ACTION_MENU:
if(mFragment == null) {
return null;
}
return new ActionDescriptionPair(
RedditAPICommentAction.RedditCommentAction.ACTION_MENU,
R.string.action_actionmenu_short);
case PROPERTIES:
return new ActionDescriptionPair(
RedditAPICommentAction.RedditCommentAction.PROPERTIES,
R.string.action_properties);
case BACK:
return new ActionDescriptionPair(
RedditAPICommentAction.RedditCommentAction.BACK,
R.string.action_back);
case DISABLED:
return null;
}
return null;
}
@NonNull
@Override
protected String getFlingLeftText() {
final Context context = getContext();
final PrefsUtility.CommentFlingAction pref = PrefsUtility.pref_behaviour_fling_comment_left(
context,
PreferenceManager.getDefaultSharedPreferences(context));
mLeftFlingAction = chooseFlingAction(pref);
if(mLeftFlingAction == null) {
return "Disabled";
}
return context.getString(mLeftFlingAction.descriptionRes);
}
@NonNull
@Override
protected String getFlingRightText() {
final Context context = getContext();
final PrefsUtility.CommentFlingAction pref = PrefsUtility.pref_behaviour_fling_comment_right(
context,
PreferenceManager.getDefaultSharedPreferences(context));
mRightFlingAction = chooseFlingAction(pref);
if(mRightFlingAction == null) {
return "Disabled";
}
return context.getString(mRightFlingAction.descriptionRes);
}
@Override
protected boolean allowFlingingLeft() {
return mLeftFlingAction != null;
}
@Override
protected boolean allowFlingingRight() {
return mRightFlingAction != null;
}
@Override
protected void onFlungLeft() {
if(mLeftFlingAction == null || !mComment.isComment()) {
return;
}
RedditAPICommentAction.onActionMenuItemSelected(
mComment.asComment(),
this,
mActivity,
mFragment,
mLeftFlingAction.action,
mChangeDataManager);
}
@Override
protected void onFlungRight() {
if(mRightFlingAction == null || !mComment.isComment()) {
return;
}
RedditAPICommentAction.onActionMenuItemSelected(
mComment.asComment(),
this,
mActivity,
mFragment,
mRightFlingAction.action,
mChangeDataManager);
}
public interface CommentListener {
void onCommentClicked(RedditCommentView view);
void onCommentLongClicked(RedditCommentView view);
}
public RedditCommentView(
final AppCompatActivity context,
final RRThemeAttributes themeAttributes,
final CommentListener listener,
final CommentListingFragment fragment) {
super(context);
mActivity = context;
mTheme = themeAttributes;
mListener = listener;
mFragment = fragment;
mChangeDataManager = RedditChangeDataManager.getInstance(
RedditAccountManager.getInstance(context).getDefaultAccount());
final View rootView = LayoutInflater.from(context).inflate(R.layout.reddit_comment, this, true);
mIndentView = (IndentView)rootView.findViewById(R.id.view_reddit_comment_indentview);
mHeader = (TextView)rootView.findViewById(R.id.view_reddit_comment_header);
mBodyHolder = (FrameLayout)rootView.findViewById(R.id.view_reddit_comment_bodyholder);
mIndentedContent = (LinearLayout)rootView.findViewById(R.id.view_reddit_comment_indented_content);
mFontScale = PrefsUtility.appearance_fontscale_comments(context, PreferenceManager.getDefaultSharedPreferences(context));
mHeader.setTextSize(TypedValue.COMPLEX_UNIT_PX, mHeader.getTextSize() * mFontScale);
mShowLinkButtons = PrefsUtility.pref_appearance_linkbuttons(context, PreferenceManager.getDefaultSharedPreferences(context));
setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View view) {
mListener.onCommentClicked(RedditCommentView.this);
}
});
setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(final View v) {
mListener.onCommentLongClicked(RedditCommentView.this);
return true;
}
});
}
@Override
public void onRedditDataChange(final String thingIdAndType) {
HANDLER.sendMessage(Message.obtain(HANDLER, HANDLER_REQUEST_COMMENT_CHANGED, this));
}
private void update() {
reset(mActivity, mComment, true);
}
public void reset(final AppCompatActivity activity, final RedditCommentListItem comment) {
reset(activity, comment, false);
}
public void reset(final AppCompatActivity activity, final RedditCommentListItem comment, final boolean updateOnly) {
if(!updateOnly) {
if(!comment.isComment()) {
throw new RuntimeException("Not a comment");
}
if(mComment != comment) {
if(mComment != null) {
mChangeDataManager.removeListener(mComment.asComment(), this);
}
mChangeDataManager.addListener(comment.asComment(), this);
}
mComment = comment;
resetSwipeState();
}
mIndentView.setIndentation(comment.getIndent());
final boolean hideLinkButtons = comment.asComment().getParsedComment().getRawComment().author.equalsIgnoreCase("autowikibot");
mBodyHolder.removeAllViews();
final View commentBody = comment.asComment().getBody(
activity,
mTheme.rrCommentBodyCol,
13.0f * mFontScale,
mShowLinkButtons && !hideLinkButtons);
mBodyHolder.addView(commentBody);
commentBody.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
((MarginLayoutParams)commentBody.getLayoutParams()).topMargin = General.dpToPixels(activity, 1);
final RedditRenderableComment renderableComment = mComment.asComment();
final CharSequence headerText = renderableComment.getHeader(
mTheme,
mChangeDataManager,
activity);
if(mComment.isCollapsed(mChangeDataManager)) {
setFlingingEnabled(false);
mHeader.setText("[ + ] " + headerText); // Note that this removes formatting (which is fine)
mBodyHolder.setVisibility(GONE);
} else {
setFlingingEnabled(true);
mHeader.setText(headerText);
mBodyHolder.setVisibility(VISIBLE);
}
}
public RedditCommentListItem getComment() {
return mComment;
}
}