/******************************************************************************* * 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.content.SharedPreferences; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.os.Build; 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.UiThread; 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.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import org.quantumbadger.redreader.R; import org.quantumbadger.redreader.common.PrefsUtility; import org.quantumbadger.redreader.fragments.PostListingFragment; import org.quantumbadger.redreader.reddit.prepared.RedditPreparedPost; public final class RedditPostView extends FlingableItemView implements RedditPreparedPost.ThumbnailLoadedCallback { private final float dpScale; private RedditPreparedPost post = null; private final TextView title, subtitle; private final ImageView thumbnailView, overlayIcon; private final LinearLayout mOuterView; private final LinearLayout commentsButton; private final TextView commentsText; private int usageId = 0; private final Handler thumbnailHandler; private final AppCompatActivity mActivity; private final PrefsUtility.PostFlingAction mLeftFlingPref, mRightFlingPref; private ActionDescriptionPair mLeftFlingAction, mRightFlingAction; private final int rrPostTitleReadCol, rrPostTitleCol, rrListItemBackgroundCol, rrPostCommentsButtonBackCol; @Override protected void onSetItemFlingPosition(final float position) { mOuterView.setTranslationX(position); } @NonNull @Override protected String getFlingLeftText() { mLeftFlingAction = chooseFlingAction(mLeftFlingPref); if(mLeftFlingAction != null) { return mActivity.getString(mLeftFlingAction.descriptionRes); } else { return "Disabled"; } } @NonNull @Override protected String getFlingRightText() { mRightFlingAction = chooseFlingAction(mRightFlingPref); if(mRightFlingAction != null) { return mActivity.getString(mRightFlingAction.descriptionRes); } else { return "Disabled"; } } @Override protected boolean allowFlingingLeft() { return mLeftFlingAction != null; } @Override protected boolean allowFlingingRight() { return mRightFlingAction != null; } @Override protected void onFlungLeft() { RedditPreparedPost.onActionMenuItemSelected(post, mActivity, mLeftFlingAction.action); } @Override protected void onFlungRight() { RedditPreparedPost.onActionMenuItemSelected(post, mActivity, mRightFlingAction.action); } private final class ActionDescriptionPair { public final RedditPreparedPost.Action action; public final int descriptionRes; private ActionDescriptionPair(RedditPreparedPost.Action action, int descriptionRes) { this.action = action; this.descriptionRes = descriptionRes; } } private ActionDescriptionPair chooseFlingAction(PrefsUtility.PostFlingAction pref) { switch(pref) { case UPVOTE: if(post.isUpvoted()) { return new ActionDescriptionPair(RedditPreparedPost.Action.UNVOTE, R.string.action_vote_remove); } else { return new ActionDescriptionPair(RedditPreparedPost.Action.UPVOTE, R.string.action_upvote); } case DOWNVOTE: if(post.isDownvoted()) { return new ActionDescriptionPair(RedditPreparedPost.Action.UNVOTE, R.string.action_vote_remove); } else { return new ActionDescriptionPair(RedditPreparedPost.Action.DOWNVOTE, R.string.action_downvote); } case SAVE: if(post.isSaved()) { return new ActionDescriptionPair(RedditPreparedPost.Action.UNSAVE, R.string.action_unsave); } else { return new ActionDescriptionPair(RedditPreparedPost.Action.SAVE, R.string.action_save); } case HIDE: if(post.isHidden()) { return new ActionDescriptionPair(RedditPreparedPost.Action.UNHIDE, R.string.action_unhide); } else { return new ActionDescriptionPair(RedditPreparedPost.Action.HIDE, R.string.action_hide); } case COMMENTS: return new ActionDescriptionPair(RedditPreparedPost.Action.COMMENTS, R.string.action_comments_short); case LINK: return new ActionDescriptionPair(RedditPreparedPost.Action.LINK, R.string.action_link_short); case BROWSER: return new ActionDescriptionPair(RedditPreparedPost.Action.EXTERNAL, R.string.action_external_short); case ACTION_MENU: return new ActionDescriptionPair(RedditPreparedPost.Action.ACTION_MENU, R.string.action_actionmenu_short); case BACK: return new ActionDescriptionPair(RedditPreparedPost.Action.BACK, R.string.action_back); } return null; } public RedditPostView( final Context context, final PostListingFragment fragmentParent, final AppCompatActivity activity) { super(context); mActivity = activity; thumbnailHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(final Message msg) { if(usageId != msg.what) return; thumbnailView.setImageBitmap((Bitmap)msg.obj); } }; dpScale = context.getResources().getDisplayMetrics().density; // TODO xml? final float fontScale = PrefsUtility.appearance_fontscale_posts(context, PreferenceManager.getDefaultSharedPreferences(context)); final View rootView = LayoutInflater.from(context).inflate(R.layout.reddit_post, this, true); mOuterView = (LinearLayout)rootView.findViewById(R.id.reddit_post_layout); mOuterView.setOnClickListener(new OnClickListener() { @Override public void onClick(final View v) { fragmentParent.onPostSelected(post); } }); mOuterView.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(final View v) { RedditPreparedPost.showActionMenu(mActivity, post); return true; } }); thumbnailView = (ImageView) rootView.findViewById(R.id.reddit_post_thumbnail_view); overlayIcon = (ImageView) rootView.findViewById(R.id.reddit_post_overlay_icon); title = (TextView) rootView.findViewById(R.id.reddit_post_title); subtitle = (TextView) rootView.findViewById(R.id.reddit_post_subtitle); commentsButton = (LinearLayout) rootView.findViewById(R.id.reddit_post_comments_button); commentsText = (TextView)commentsButton.findViewById(R.id.reddit_post_comments_text); commentsButton.setOnClickListener(new OnClickListener() { @Override public void onClick(final View v) { fragmentParent.onPostCommentsSelected(post); } }); title.setTextSize(TypedValue.COMPLEX_UNIT_PX, title.getTextSize() * fontScale); subtitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, subtitle.getTextSize() * fontScale); final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); mLeftFlingPref = PrefsUtility.pref_behaviour_fling_post_left(context, sharedPreferences); mRightFlingPref = PrefsUtility.pref_behaviour_fling_post_right(context, sharedPreferences); { final TypedArray attr = context.obtainStyledAttributes(new int[]{ R.attr.rrPostTitleCol, R.attr.rrPostTitleReadCol, R.attr.rrListItemBackgroundCol, R.attr.rrPostCommentsButtonBackCol }); rrPostTitleCol = attr.getColor(0, 0); rrPostTitleReadCol = attr.getColor(1, 0); rrListItemBackgroundCol = attr.getColor(2, 0); rrPostCommentsButtonBackCol = attr.getColor(3, 0); attr.recycle(); } } @UiThread public void reset(final RedditPreparedPost data) { if(data != post) { usageId++; resetSwipeState(); final Bitmap thumbnail = data.getThumbnail(this, usageId); thumbnailView.setImageBitmap(thumbnail); title.setText(data.src.getTitle()); commentsText.setText(String.valueOf(data.src.getSrc().num_comments)); if(data.hasThumbnail) { thumbnailView.setVisibility(VISIBLE); thumbnailView.setMinimumWidth((int)(64.0f * dpScale)); // TODO remove constant, customise thumbnailView.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT; } else { thumbnailView.setMinimumWidth(0); thumbnailView.setVisibility(GONE); } } if(post != null) post.unbind(this); data.bind(this); this.post = data; updateAppearance(); } public void updateAppearance() { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { mOuterView.setBackgroundResource(R.drawable.rr_postlist_item_selector_main); commentsButton.setBackgroundResource(R.drawable.rr_postlist_commentbutton_selector_main); } else { // On KitKat and lower, we can't do easily themed highlighting mOuterView.setBackgroundColor(rrListItemBackgroundCol); commentsButton.setBackgroundColor(rrPostCommentsButtonBackCol); } if(post.isRead()) { title.setTextColor(rrPostTitleReadCol); } else { title.setTextColor(rrPostTitleCol); } subtitle.setText(post.postListDescription); boolean overlayVisible = true; if(post.isSaved()) { overlayIcon.setImageResource(R.drawable.ic_action_star_filled_dark); } else if(post.isHidden()) { overlayIcon.setImageResource(R.drawable.ic_action_cross_dark); } else if(post.isUpvoted()) { overlayIcon.setImageResource(R.drawable.action_upvote_dark); } else if(post.isDownvoted()) { overlayIcon.setImageResource(R.drawable.action_downvote_dark); } else { overlayVisible = false; } if(overlayVisible) { overlayIcon.setVisibility(VISIBLE); } else { overlayIcon.setVisibility(GONE); } } public void betterThumbnailAvailable(final Bitmap thumbnail, final int callbackUsageId) { final Message msg = Message.obtain(); msg.obj = thumbnail; msg.what = callbackUsageId; thumbnailHandler.sendMessage(msg); } public interface PostSelectionListener { void onPostSelected(RedditPreparedPost post); void onPostCommentsSelected(RedditPreparedPost post); } }