package com.kenny.openimgur.ui.adapters; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.media.MediaPlayer; import android.support.annotation.Nullable; import android.support.design.widget.FloatingActionButton; import android.support.v4.content.res.ResourcesCompat; import android.text.TextUtils; import android.text.format.DateUtils; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import com.kenny.openimgur.R; import com.kenny.openimgur.classes.ImgurBaseObject; import com.kenny.openimgur.classes.ImgurListener; import com.kenny.openimgur.classes.ImgurPhoto; import com.kenny.openimgur.ui.PointsBar; import com.kenny.openimgur.ui.VideoView; import com.kenny.openimgur.util.FileUtil; import com.kenny.openimgur.util.ImageUtil; import com.nostra13.universalimageloader.core.DisplayImageOptions; import java.util.List; import butterknife.BindView; import pl.droidsonroids.gif.GifDrawable; public class PhotoAdapter extends BaseRecyclerAdapter<ImgurPhoto> { private static final int VIEW_HEADER = 1; private static final int VIEW_PHOTO = 2; private static final long PHOTO_SIZE_LIMIT = 1024 * 1024 * 2; private static final long PHOTO_PIXEL_LIMIT = 2048; ImgurListener mListener; ImgurBaseObject mImgurObject; public PhotoAdapter(Context context, List<ImgurPhoto> photos, ImgurBaseObject object, ImgurListener listener) { super(context, photos, true); mListener = listener; mImgurObject = object; } /** * Removes all items from list and ImgurListener is removed */ @Override public void onDestroy() { mListener = null; super.onDestroy(); } @Override protected DisplayImageOptions getDisplayOptions() { return ImageUtil.getDisplayOptionsForView().build(); } @Override public int getItemViewType(int position) { return position == 0 ? VIEW_HEADER : VIEW_PHOTO; } @Override public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { BaseViewHolder holder; if (viewType == VIEW_HEADER) { holder = new PhotoTitleHolder(inflateView(R.layout.image_header, parent)); } else { holder = new PhotoViewHolder(inflateView(R.layout.view_photo_item, parent)); setClickListener((PhotoViewHolder) holder); holder.itemView.setTag(holder); } return holder; } @Override public int getItemCount() { // Pad the count for the header return super.getItemCount() + 1; } @Override public void onBindViewHolder(BaseViewHolder holder, int position) { // Remove one from position to account for the header position--; if (holder instanceof PhotoTitleHolder) { PhotoTitleHolder titleHolder = (PhotoTitleHolder) holder; if (!TextUtils.isEmpty(mImgurObject.getTitle())) titleHolder.title.setText(mImgurObject.getTitle()); if (!TextUtils.isEmpty(mImgurObject.getTopic())) titleHolder.topic.setText(mImgurObject.getTopic()); titleHolder.author.setText(getAuthorDateLine(mImgurObject.getAccount(), mImgurObject.getDate())); int totalPoints = mImgurObject.getDownVotes() + mImgurObject.getUpVotes(); int votePoints = mImgurObject.getUpVotes() - mImgurObject.getDownVotes(); titleHolder.points.setText(getResources().getQuantityString(R.plurals.points, votePoints, votePoints)); titleHolder.pointsBar.setPoints(mImgurObject.getUpVotes(), totalPoints); if (mImgurObject.isFavorited() || ImgurBaseObject.VOTE_UP.equals(mImgurObject.getVote())) { titleHolder.points.setTextColor(getColor(R.color.notoriety_positive)); } else if (ImgurBaseObject.VOTE_DOWN.equals(mImgurObject.getVote())) { titleHolder.points.setTextColor(getColor(R.color.notoriety_negative)); } if (mImgurObject.getTags() != null && !mImgurObject.getTags().isEmpty()) { Drawable tagDrawable; int size = mImgurObject.getTags().size(); StringBuilder builder = new StringBuilder(); // Tag icon is already dark themed if (isDarkTheme) { tagDrawable = ResourcesCompat.getDrawable(getResources(), R.drawable.ic_action_tag_16dp, null); } else { tagDrawable = ImageUtil.tintDrawable(R.drawable.ic_action_tag_16dp, getResources(), Color.BLACK); } for (int i = 0; i < size; i++) { builder.append(mImgurObject.getTags().get(i).getName()); if (i != size - 1) builder.append(", "); } titleHolder.tags.setText(builder.toString()); titleHolder.tags.setCompoundDrawablesWithIntrinsicBounds(tagDrawable, null, null, null); titleHolder.tags.setVisibility(View.VISIBLE); } } else { PhotoViewHolder photoHolder = (PhotoViewHolder) holder; ImgurPhoto photo = getItem(position); String url = getPhotoUrl(photo); photoHolder.prog.setVisibility(View.GONE); photoHolder.video.setVisibility(View.GONE); photoHolder.image.setVisibility(View.VISIBLE); if (photoHolder.video.isPlaying()) { photoHolder.video.stopPlayback(); } if (photo.isAnimated()) { photoHolder.play.setVisibility(View.VISIBLE); } else { photoHolder.play.setVisibility(View.GONE); } if (!TextUtils.isEmpty(photo.getDescription())) { photoHolder.desc.setVisibility(View.VISIBLE); photoHolder.desc.setText(photo.getDescription()); } else { photoHolder.desc.setVisibility(View.GONE); } // Don't display titles for items with only 1 photo, it will be shown in the header if (!TextUtils.isEmpty(photo.getTitle()) && getItemCount() - 1 > 1) { photoHolder.title.setVisibility(View.VISIBLE); photoHolder.title.setText(photo.getTitle()); } else { photoHolder.title.setVisibility(View.GONE); } //Linkify.addLinks(photoHolder.title, Linkify.WEB_URLS); //Linkify.addLinks(photoHolder.title, LinkUtils.USER_CALLOUT_PATTERN, null); //Linkify.addLinks(photoHolder.desc, Linkify.WEB_URLS); //Linkify.addLinks(photoHolder.desc, LinkUtils.USER_CALLOUT_PATTERN, null); displayImage(photoHolder.image, url); } } /** * Sets all the click listeners for the appropriate views * * @param holder */ private void setClickListener(final PhotoViewHolder holder) { holder.play.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (mListener != null) { mListener.onPlayTap(holder.prog, holder.play, holder.image, holder.video, holder.itemView); } } }); holder.image.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (mListener != null) { mListener.onPhotoTap(holder.itemView); } } }); holder.video.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { if (motionEvent.getAction() == MotionEvent.ACTION_UP && mListener != null) { mListener.onPhotoTap(holder.itemView); } return true; } }); holder.image.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { if (mListener != null) { mListener.onPhotoLongTapListener(holder.itemView); } return true; } }); holder.video.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mediaPlayer) { mediaPlayer.setLooping(true); } }); //holder.title.setMovementMethod(CustomLinkMovement.getInstance()); //holder.desc.setMovementMethod(CustomLinkMovement.getInstance()); } /** * Returns the photo url for the ImgurPhoto Object * * @param photo * @return */ private String getPhotoUrl(ImgurPhoto photo) { String url; // Check if we have an mp4 and if we should load its thumbnail if (photo.isAnimated() && photo.hasVideoLink() && photo.isLinkAThumbnail()) { if (photo.getSize() > PHOTO_SIZE_LIMIT || photo.getHeight() > PHOTO_PIXEL_LIMIT || photo.getWidth() > PHOTO_PIXEL_LIMIT) { url = photo.getThumbnail(ImgurPhoto.THUMBNAIL_HUGE, true, FileUtil.EXTENSION_GIF); } else { url = photo.getLink(); } } else if (photo.getSize() > PHOTO_SIZE_LIMIT || photo.getHeight() > PHOTO_PIXEL_LIMIT || photo.getWidth() > PHOTO_PIXEL_LIMIT) { url = photo.getThumbnail(ImgurPhoto.THUMBNAIL_HUGE, false, null); } else { url = photo.getLink(); } return url; } /** * Attempts to pause the currently playing gif or video * * @param view * @return If pausing was successfully */ public boolean attemptToPause(View view) { if (!(view.getTag() instanceof PhotoViewHolder)) return false; PhotoViewHolder holder = (PhotoViewHolder) view.getTag(); if (holder.image.getDrawable() instanceof GifDrawable) { GifDrawable gif = (GifDrawable) holder.image.getDrawable(); if (gif.isPlaying()) { gif.pause(); holder.play.setVisibility(View.VISIBLE); return true; } } else if (holder.video.isPlaying()) { holder.video.pause(); holder.play.setVisibility(View.VISIBLE); return true; } return false; } private CharSequence getAuthorDateLine(@Nullable String username, long commentDate) { StringBuilder sb = new StringBuilder("- "); sb.append(TextUtils.isEmpty(username) ? "?????" : username); if (commentDate > 0) { // The comment date comes in seconds sb.append(", "); commentDate = commentDate * DateUtils.SECOND_IN_MILLIS; long now = System.currentTimeMillis(); long difference = System.currentTimeMillis() - commentDate; if (difference >= 0 && difference <= DateUtils.MINUTE_IN_MILLIS) { sb.append(getString(R.string.moments_ago)); } else { sb.append(DateUtils.getRelativeTimeSpanString( commentDate, now, DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_RELATIVE | DateUtils.FORMAT_ABBREV_ALL)); } } return sb.toString(); } @Override public void onViewRecycled(BaseViewHolder holder) { super.onViewRecycled(holder); if (holder instanceof PhotoViewHolder) { PhotoViewHolder photoViewHolder = (PhotoViewHolder) holder; if (photoViewHolder.image.getDrawable() instanceof GifDrawable) { GifDrawable gif = (GifDrawable) photoViewHolder.image.getDrawable(); gif.stop(); gif.recycle(); } photoViewHolder.video.stopPlayback(); } } static class PhotoViewHolder extends BaseViewHolder { @BindView(R.id.image) ImageView image; @BindView(R.id.play) FloatingActionButton play; @BindView(R.id.progressBar) ProgressBar prog; @BindView(R.id.desc) TextView desc; @BindView(R.id.title) TextView title; @BindView(R.id.videoView) VideoView video; public PhotoViewHolder(View view) { super(view); } } static class PhotoTitleHolder extends BaseViewHolder { @BindView(R.id.title) TextView title; @BindView(R.id.author) TextView author; @BindView(R.id.pointText) TextView points; @BindView(R.id.topic) TextView topic; @BindView(R.id.tags) TextView tags; @BindView(R.id.pointsBar) PointsBar pointsBar; public PhotoTitleHolder(View view) { super(view); } } }