package me.ccrama.redditslide.Adapters; /** * Created by ccrama on 3/22/2015. */ import android.app.Activity; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.Typeface; import android.os.AsyncTask; import android.support.design.widget.Snackbar; import android.support.v7.widget.RecyclerView; import android.text.Html; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.style.ForegroundColorSpan; import android.text.style.ImageSpan; import android.text.style.RelativeSizeSpan; import android.text.style.StyleSpan; 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 com.afollestad.materialdialogs.AlertDialogWrapper; import com.cocosw.bottomsheet.BottomSheet; import com.devspark.robototextview.util.RobotoTypefaceManager; import net.dean.jraw.managers.AccountManager; import net.dean.jraw.models.Comment; import net.dean.jraw.models.Contribution; import net.dean.jraw.models.Submission; import net.dean.jraw.models.VoteDirection; import java.util.List; import java.util.Locale; import me.ccrama.redditslide.ActionStates; import me.ccrama.redditslide.Activities.Profile; import me.ccrama.redditslide.Activities.SubredditView; import me.ccrama.redditslide.Activities.Website; import me.ccrama.redditslide.Authentication; import me.ccrama.redditslide.HasSeen; import me.ccrama.redditslide.Hidden; import me.ccrama.redditslide.OpenRedditLink; import me.ccrama.redditslide.R; import me.ccrama.redditslide.Reddit; import me.ccrama.redditslide.SettingValues; import me.ccrama.redditslide.SubmissionViews.PopulateSubmissionViewHolder; import me.ccrama.redditslide.TimeUtils; import me.ccrama.redditslide.Views.CatchStaggeredGridLayoutManager; import me.ccrama.redditslide.Views.CreateCardView; import me.ccrama.redditslide.Visuals.FontPreferences; import me.ccrama.redditslide.Visuals.Palette; import me.ccrama.redditslide.util.SubmissionParser; public class ContributionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements BaseAdapter { private final int SPACER = 6; private static final int COMMENT = 1; public final Activity mContext; private final RecyclerView listView; private final Boolean isHiddenPost; public GeneralPosts dataSet; public ContributionAdapter(Activity mContext, GeneralPosts dataSet, RecyclerView listView) { this.mContext = mContext; this.listView = listView; this.dataSet = dataSet; this.isHiddenPost = false; } public ContributionAdapter(Activity mContext, GeneralPosts dataSet, RecyclerView listView, Boolean isHiddenPost) { this.mContext = mContext; this.listView = listView; this.dataSet = dataSet; this.isHiddenPost = isHiddenPost; } private final int LOADING_SPINNER = 5; private final int NO_MORE = 3; @Override public int getItemViewType(int position) { if (position == 0 && !dataSet.posts.isEmpty()) { return SPACER; } else if (!dataSet.posts.isEmpty()) { position -= 1; } if (position == dataSet.posts.size() && !dataSet.posts.isEmpty() && !dataSet.nomore) { return LOADING_SPINNER; } else if (position == dataSet.posts.size() && dataSet.nomore) { return NO_MORE; } if (dataSet.posts.get(position) instanceof Comment) return COMMENT; return 2; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { if (i == SPACER) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.spacer, viewGroup, false); return new SpacerViewHolder(v); } else if (i == COMMENT) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.profile_comment, viewGroup, false); return new ProfileCommentViewHolder(v); } else if (i == LOADING_SPINNER) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.loadingmore, viewGroup, false); return new SubmissionFooterViewHolder(v); } else if (i == NO_MORE) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.nomoreposts, viewGroup, false); return new SubmissionFooterViewHolder(v); } else { View v = CreateCardView.CreateView(viewGroup); return new SubmissionViewHolder(v); } } public class SubmissionFooterViewHolder extends RecyclerView.ViewHolder { public SubmissionFooterViewHolder(View itemView) { super(itemView); } } public class AsyncSave extends AsyncTask<Submission, Void, Void> { View v; public AsyncSave(View v) { this.v = v; } @Override protected Void doInBackground(Submission... submissions) { try { if (ActionStates.isSaved(submissions[0])) { new AccountManager(Authentication.reddit).unsave(submissions[0]); final Snackbar s = Snackbar.make(v, R.string.submission_info_unsaved, Snackbar.LENGTH_SHORT); mContext.runOnUiThread(new Runnable() { @Override public void run() { View view = s.getView(); TextView tv = (TextView) view.findViewById(android.support.design.R.id.snackbar_text); tv.setTextColor(Color.WHITE); s.show(); } }); submissions[0].saved = false; v = null; } else { new AccountManager(Authentication.reddit).save(submissions[0]); final Snackbar s = Snackbar.make(v, R.string.submission_info_saved, Snackbar.LENGTH_SHORT); mContext.runOnUiThread(new Runnable() { @Override public void run() { View view = s.getView(); TextView tv = (TextView) view.findViewById(android.support.design.R.id.snackbar_text); tv.setTextColor(Color.WHITE); s.show(); } }); submissions[0].saved = true; v = null; } } catch (Exception e) { return null; } return null; } } @Override public void onBindViewHolder(final RecyclerView.ViewHolder firstHolder, final int pos) { int i = pos != 0 ? pos - 1 : pos; if (firstHolder instanceof SubmissionViewHolder) { final SubmissionViewHolder holder = (SubmissionViewHolder) firstHolder; final Submission submission = (Submission) dataSet.posts.get(i); CreateCardView.resetColorCard(holder.itemView); if (submission.getSubredditName() != null) CreateCardView.colorCard(submission.getSubredditName().toLowerCase(), holder.itemView, "no_subreddit", false); holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { LayoutInflater inflater = mContext.getLayoutInflater(); final View dialoglayout = inflater.inflate(R.layout.postmenu, null); AlertDialogWrapper.Builder builder = new AlertDialogWrapper.Builder(mContext); final TextView title = (TextView) dialoglayout.findViewById(R.id.title); title.setText(Html.fromHtml(submission.getTitle())); ((TextView) dialoglayout.findViewById(R.id.userpopup)).setText("/u/" + submission.getAuthor()); ((TextView) dialoglayout.findViewById(R.id.subpopup)).setText("/r/" + submission.getSubredditName()); dialoglayout.findViewById(R.id.sidebar).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent i = new Intent(mContext, Profile.class); i.putExtra(Profile.EXTRA_PROFILE, submission.getAuthor()); mContext.startActivity(i); } }); dialoglayout.findViewById(R.id.wiki).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent i = new Intent(mContext, SubredditView.class); i.putExtra(SubredditView.EXTRA_SUBREDDIT, submission.getSubredditName()); mContext.startActivity(i); } }); dialoglayout.findViewById(R.id.save).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (submission.isSaved()) { ((TextView) dialoglayout.findViewById(R.id.savedtext)).setText(R.string.submission_save); } else { ((TextView) dialoglayout.findViewById(R.id.savedtext)).setText(R.string.submission_post_saved); } new AsyncSave(firstHolder.itemView).execute(submission); } }); dialoglayout.findViewById(R.id.copy).setVisibility(View.GONE); if (submission.isSaved()) { ((TextView) dialoglayout.findViewById(R.id.savedtext)).setText(R.string.submission_post_saved); } dialoglayout.findViewById(R.id.gild).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String urlString = "https://reddit.com" + submission.getPermalink(); Intent i = new Intent(mContext, Website.class); i.putExtra(Website.EXTRA_URL, urlString); mContext.startActivity(i); } }); dialoglayout.findViewById(R.id.share).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (submission.isSelfPost()) Reddit.defaultShareText("", "https://reddit.com" + submission.getPermalink(), mContext); else { new BottomSheet.Builder(mContext) .title(R.string.submission_share_title) .grid() .sheet(R.menu.share_menu) .listener(new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case R.id.reddit_url: Reddit.defaultShareText("", "https://reddit.com" + submission.getPermalink(), mContext); break; case R.id.link_url: Reddit.defaultShareText(submission.getTitle(), submission.getUrl(), mContext); break; } } }).show(); } } }); if (!Authentication.isLoggedIn || !Authentication.didOnline) { dialoglayout.findViewById(R.id.save).setVisibility(View.GONE); dialoglayout.findViewById(R.id.gild).setVisibility(View.GONE); } title.setBackgroundColor(Palette.getColor(submission.getSubredditName())); builder.setView(dialoglayout); final Dialog d = builder.show(); dialoglayout.findViewById(R.id.hide).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final int pos = dataSet.posts.indexOf(submission); final Contribution old = dataSet.posts.get(pos); dataSet.posts.remove(submission); notifyItemRemoved(pos + 1); d.dismiss(); Hidden.setHidden(old); Snackbar s = Snackbar.make(listView, R.string.submission_info_hidden, Snackbar.LENGTH_LONG).setAction(R.string.btn_undo, new View.OnClickListener() { @Override public void onClick(View v) { dataSet.posts.add(pos, old); notifyItemInserted(pos + 1); Hidden.undoHidden(old); } }); View view = s.getView(); TextView tv = (TextView) view.findViewById(android.support.design.R.id.snackbar_text); tv.setTextColor(Color.WHITE); s.show(); } }); return true; } }); new PopulateSubmissionViewHolder().populateSubmissionViewHolder(holder, submission, mContext, false, false, dataSet.posts, listView, false, false, null, null); final ImageView hideButton = (ImageView) holder.itemView.findViewById(R.id.hide); if (hideButton != null && isHiddenPost) { hideButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final int pos = dataSet.posts.indexOf(submission); final Contribution old = dataSet.posts.get(pos); dataSet.posts.remove(submission); notifyItemRemoved(pos + 1); Hidden.undoHidden(old); } }); } holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String url = "www.reddit.com" + submission.getPermalink(); url = url.replace("?ref=search_posts", ""); new OpenRedditLink(mContext, url); if (SettingValues.storeHistory) { if (SettingValues.storeNSFWHistory && submission.isNsfw() || !submission.isNsfw()) HasSeen.addSeen(submission.getFullName()); } notifyItemChanged(pos); } }); } else if (firstHolder instanceof ProfileCommentViewHolder) { //IS COMMENT ProfileCommentViewHolder holder = (ProfileCommentViewHolder) firstHolder; final Comment comment = (Comment) dataSet.posts.get(i); String scoreText; if (comment.isScoreHidden()) { scoreText = "[" + mContext.getString(R.string.misc_score_hidden).toUpperCase() + "]"; } else { scoreText = String.format(Locale.getDefault(), "%d", comment.getScore()); } SpannableStringBuilder score = new SpannableStringBuilder(scoreText); if (score == null || score.toString().isEmpty()) { score = new SpannableStringBuilder("0"); } if (!scoreText.contains("[")) { score.append(String.format(Locale.getDefault(), " %s", mContext.getResources().getQuantityString(R.plurals.points, comment.getScore()))); } holder.score.setText(score); if (Authentication.isLoggedIn) { if (ActionStates.getVoteDirection(comment) == VoteDirection.UPVOTE) { holder.score.setTextColor(mContext.getResources().getColor(R.color.md_orange_500)); } else if (ActionStates.getVoteDirection(comment) == VoteDirection.DOWNVOTE) { holder.score.setTextColor(mContext.getResources().getColor(R.color.md_blue_500)); } else { holder.score.setTextColor(holder.time.getCurrentTextColor()); } } String spacer = mContext.getString(R.string.submission_properties_seperator); SpannableStringBuilder titleString = new SpannableStringBuilder(); String timeAgo = TimeUtils.getTimeAgo(comment.getCreated().getTime(), mContext); String time = ((timeAgo == null || timeAgo.isEmpty()) ? "just now" : timeAgo); //some users were crashing here time = time + (((comment.getEditDate() != null) ? " (edit " + TimeUtils.getTimeAgo(comment.getEditDate().getTime(), mContext) + ")" : "")); titleString.append(time); titleString.append(spacer); if (comment.getSubredditName() != null) { String subname = comment.getSubredditName(); SpannableStringBuilder subreddit = new SpannableStringBuilder("/r/" + subname); if ((SettingValues.colorSubName && Palette.getColor(subname) != Palette.getDefaultColor())) { subreddit.setSpan(new ForegroundColorSpan(Palette.getColor(subname)), 0, subreddit.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); subreddit.setSpan(new StyleSpan(Typeface.BOLD), 0, subreddit.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } titleString.append(subreddit); } holder.time.setText(titleString); setViews(comment.getDataNode().get("body_html").asText(), comment.getSubredditName(), holder); int type = new FontPreferences(mContext).getFontTypeComment().getTypeface(); Typeface typeface; if (type >= 0) { typeface = RobotoTypefaceManager.obtainTypeface(mContext, type); } else { typeface = Typeface.DEFAULT; } holder.content.setTypeface(typeface); if (comment.getTimesGilded() > 0) { final String timesGilded = (comment.getTimesGilded() == 1) ? "" : "\u200Ax" + Integer.toString(comment.getTimesGilded()); SpannableStringBuilder gilded = new SpannableStringBuilder("\u00A0★" + timesGilded + "\u00A0"); TypedArray a = mContext.obtainStyledAttributes(new FontPreferences(mContext).getPostFontStyle().getResId(), R.styleable.FontStyle); int fontsize = (int) (a.getDimensionPixelSize(R.styleable.FontStyle_font_cardtitle, -1)*.75); a.recycle(); Bitmap image = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.gold); float aspectRatio = (float) (1.00 * image.getWidth() / image.getHeight()); image = Bitmap.createScaledBitmap(image, (int) Math.ceil(fontsize * aspectRatio), (int) Math.ceil(fontsize), true); gilded.setSpan(new ImageSpan(mContext, image, ImageSpan.ALIGN_BASELINE), 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); gilded.setSpan(new RelativeSizeSpan(0.75f), 3, gilded.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); holder.gild.setVisibility(View.VISIBLE); ((TextView) holder.gild).setText(gilded); } else if (holder.gild.getVisibility() == View.VISIBLE) holder.gild.setVisibility(View.GONE); if (comment.getSubmissionTitle() != null) holder.title.setText(Html.fromHtml(comment.getSubmissionTitle())); else holder.title.setText(Html.fromHtml(comment.getAuthor())); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new OpenRedditLink(mContext, comment.getSubmissionId(), comment.getSubredditName(), comment.getId()); } }); holder.content.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new OpenRedditLink(mContext, comment.getSubmissionId(), comment.getSubredditName(), comment.getId()); } }); } else if (firstHolder instanceof SpacerViewHolder) { firstHolder.itemView.setLayoutParams(new LinearLayout.LayoutParams(firstHolder.itemView.getWidth(), mContext.findViewById(R.id.header).getHeight())); if (listView.getLayoutManager() instanceof CatchStaggeredGridLayoutManager) { CatchStaggeredGridLayoutManager.LayoutParams layoutParams = new CatchStaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mContext.findViewById(R.id.header).getHeight()); layoutParams.setFullSpan(true); firstHolder.itemView.setLayoutParams(layoutParams); } } } public class SpacerViewHolder extends RecyclerView.ViewHolder { public SpacerViewHolder(View itemView) { super(itemView); } } private void setViews(String rawHTML, String subredditName, ProfileCommentViewHolder holder) { if (rawHTML.isEmpty()) { return; } List<String> blocks = SubmissionParser.getBlocks(rawHTML); int startIndex = 0; // the <div class="md"> case is when the body contains a table or code block first if (!blocks.get(0).equals("<div class=\"md\">")) { holder.content.setVisibility(View.VISIBLE); holder.content.setTextHtml(blocks.get(0), subredditName); startIndex = 1; } else { holder.content.setText(""); holder.content.setVisibility(View.GONE); } if (blocks.size() > 1) { if (startIndex == 0) { holder.overflow.setViews(blocks, subredditName); } else { holder.overflow.setViews(blocks.subList(startIndex, blocks.size()), subredditName); } } else { holder.overflow.removeAllViews(); } } @Override public int getItemCount() { if (dataSet.posts == null || dataSet.posts.isEmpty()) { return 0; } else { return dataSet.posts.size() + 2; } } @Override public void setError(Boolean b) { listView.setAdapter(new ErrorAdapter()); } @Override public void undoSetError() { listView.setAdapter(this); } public static class EmptyViewHolder extends RecyclerView.ViewHolder { public EmptyViewHolder(View itemView) { super(itemView); } } }