package org.getlantern.firetweet.adapter; import android.content.Context; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.util.Pair; import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView.Adapter; import android.support.v7.widget.RecyclerView.ViewHolder; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import org.getlantern.firetweet.Constants; import org.getlantern.firetweet.R; import org.getlantern.firetweet.adapter.iface.IStatusesAdapter; import org.getlantern.firetweet.app.FiretweetApplication; import org.getlantern.firetweet.fragment.support.UserFragment; import org.getlantern.firetweet.model.ParcelableMedia; import org.getlantern.firetweet.model.ParcelableStatus; import org.getlantern.firetweet.util.AsyncTwitterWrapper; import org.getlantern.firetweet.util.ImageLoadingHandler; import org.getlantern.firetweet.util.MediaLoaderWrapper; import org.getlantern.firetweet.util.SharedPreferencesWrapper; import org.getlantern.firetweet.util.StatusAdapterLinkClickHandler; import org.getlantern.firetweet.util.ThemeUtils; import org.getlantern.firetweet.util.FiretweetLinkify; import org.getlantern.firetweet.util.FiretweetLinkify.HighlightStyle; import org.getlantern.firetweet.util.Utils; import org.getlantern.firetweet.view.CardMediaContainer.PreviewStyle; import org.getlantern.firetweet.view.ShapedImageView.ShapeStyle; import org.getlantern.firetweet.view.holder.GapViewHolder; import org.getlantern.firetweet.view.holder.LoadIndicatorViewHolder; import org.getlantern.firetweet.view.holder.StatusViewHolder; /** * Created by mariotaku on 14/11/19. */ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implements Constants, IStatusesAdapter<D> { public static final int ITEM_VIEW_TYPE_LOAD_INDICATOR = 0; public static final int ITEM_VIEW_TYPE_GAP = 1; public static final int ITEM_VIEW_TYPE_STATUS = 2; private final Context mContext; private final LayoutInflater mInflater; private final MediaLoaderWrapper mImageLoader; private final ImageLoadingHandler mLoadingHandler; private final AsyncTwitterWrapper mTwitterWrapper; private final FiretweetLinkify mLinkify; private StatusAdapterListener mStatusAdapterListener; private final int mCardBackgroundColor; private final int mTextSize; @ShapeStyle private final int mProfileImageStyle; @PreviewStyle private final int mMediaPreviewStyle; @HighlightStyle private final int mLinkHighlightingStyle; private final boolean mCompactCards; private final boolean mNameFirst; private final boolean mDisplayMediaPreview; private final boolean mDisplayProfileImage; private final boolean mSensitiveContentEnabled; private final boolean mHideCardActions; private boolean mLoadMoreSupported; private boolean mLoadMoreIndicatorVisible; private boolean mShowInReplyTo; private boolean mShowAccountsColor; public AbsStatusesAdapter(Context context, boolean compact) { mContext = context; final FiretweetApplication app = FiretweetApplication.getInstance(context); mCardBackgroundColor = ThemeUtils.getCardBackgroundColor(context); mInflater = LayoutInflater.from(context); mImageLoader = app.getMediaLoaderWrapper(); mLoadingHandler = new ImageLoadingHandler(R.id.media_preview_progress); mTwitterWrapper = app.getTwitterWrapper(); final SharedPreferencesWrapper preferences = SharedPreferencesWrapper.getInstance(context, SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); mTextSize = preferences.getInt(KEY_TEXT_SIZE, context.getResources().getInteger(R.integer.default_text_size)); mCompactCards = compact; mProfileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null)); mMediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null)); mLinkHighlightingStyle = Utils.getLinkHighlightingStyleInt(preferences.getString(KEY_LINK_HIGHLIGHT_OPTION, null)); mNameFirst = preferences.getBoolean(KEY_NAME_FIRST, true); mDisplayProfileImage = preferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true); mDisplayMediaPreview = preferences.getBoolean(KEY_MEDIA_PREVIEW, false); mSensitiveContentEnabled = preferences.getBoolean(KEY_DISPLAY_SENSITIVE_CONTENTS, false); mHideCardActions = preferences.getBoolean(KEY_HIDE_CARD_ACTIONS, false); mLinkify = new FiretweetLinkify(new StatusAdapterLinkClickHandler<>(this)); setShowInReplyTo(true); } public abstract D getData(); public abstract void setData(D data); @Override public boolean shouldShowAccountsColor() { return mShowAccountsColor; } @Override public final MediaLoaderWrapper getImageLoader() { return mImageLoader; } @Override public final Context getContext() { return mContext; } @Override public final ImageLoadingHandler getImageLoadingHandler() { return mLoadingHandler; } @Override public final int getProfileImageStyle() { return mProfileImageStyle; } @Override public final int getMediaPreviewStyle() { return mMediaPreviewStyle; } @Override public final AsyncTwitterWrapper getTwitterWrapper() { return mTwitterWrapper; } @Override public final float getTextSize() { return mTextSize; } @Override public boolean isLoadMoreIndicatorVisible() { return mLoadMoreIndicatorVisible; } @Override public boolean isLoadMoreSupported() { return mLoadMoreSupported; } @Override public void setLoadMoreSupported(boolean supported) { mLoadMoreSupported = supported; if (!supported) { mLoadMoreIndicatorVisible = false; } notifyDataSetChanged(); } @Override public void setLoadMoreIndicatorVisible(boolean enabled) { if (mLoadMoreIndicatorVisible == enabled) return; mLoadMoreIndicatorVisible = enabled && mLoadMoreSupported; notifyDataSetChanged(); } @Override public FiretweetLinkify getFiretweetLinkify() { return mLinkify; } @Override public boolean isMediaPreviewEnabled() { return mDisplayMediaPreview; } @Override public int getLinkHighlightingStyle() { return mLinkHighlightingStyle; } @Override public boolean isNameFirst() { return mNameFirst; } @Override public boolean isSensitiveContentEnabled() { return mSensitiveContentEnabled; } @Override public boolean isCardActionsHidden() { return mHideCardActions; } @Override public boolean isProfileImageEnabled() { return mDisplayProfileImage; } @Override public final void onStatusClick(StatusViewHolder holder, int position) { if (mStatusAdapterListener != null) { mStatusAdapterListener.onStatusClick(holder, position); } } @Override public void onMediaClick(StatusViewHolder holder, final ParcelableMedia media, int position) { if (mStatusAdapterListener != null) { mStatusAdapterListener.onMediaClick(holder, media, position); } } @Override public void onUserProfileClick(final StatusViewHolder holder, final int position) { final ParcelableStatus status = getStatus(position); if (status == null) return; final Context context = getContext(); final View profileImageView = holder.getProfileImageView(); final View profileTypeView = holder.getProfileTypeView(); if (context instanceof FragmentActivity) { final Bundle options = Utils.makeSceneTransitionOption((FragmentActivity) context, new Pair<>(profileImageView, UserFragment.TRANSITION_NAME_PROFILE_IMAGE), new Pair<>(profileTypeView, UserFragment.TRANSITION_NAME_PROFILE_TYPE)); Utils.openUserProfile(context, status.account_id, status.user_id, status.user_screen_name, options); } else { Utils.openUserProfile(context, status.account_id, status.user_id, status.user_screen_name, null); } } public boolean isShowInReplyTo() { return mShowInReplyTo; } public void setShowInReplyTo(boolean showInReplyTo) { if (mShowInReplyTo == showInReplyTo) return; mShowInReplyTo = showInReplyTo; notifyDataSetChanged(); } public boolean isStatus(int position) { return position < getStatusesCount(); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { case ITEM_VIEW_TYPE_STATUS: { final View view; if (mCompactCards) { view = mInflater.inflate(R.layout.card_item_status_compact, parent, false); final View itemContent = view.findViewById(R.id.item_content); itemContent.setBackgroundColor(mCardBackgroundColor); } else { view = mInflater.inflate(R.layout.card_item_status, parent, false); final CardView cardView = (CardView) view.findViewById(R.id.card); cardView.setCardBackgroundColor(mCardBackgroundColor); } final StatusViewHolder holder = new StatusViewHolder(this, view); holder.setOnClickListeners(); holder.setupViewOptions(); return holder; } case ITEM_VIEW_TYPE_GAP: { final View view = mInflater.inflate(R.layout.card_item_gap, parent, false); return new GapViewHolder(this, view); } case ITEM_VIEW_TYPE_LOAD_INDICATOR: { final View view = mInflater.inflate(R.layout.card_item_load_indicator, parent, false); return new LoadIndicatorViewHolder(view); } } throw new IllegalStateException("Unknown view type " + viewType); } @Override public void onBindViewHolder(ViewHolder holder, int position) { switch (holder.getItemViewType()) { case ITEM_VIEW_TYPE_STATUS: { bindStatus(((StatusViewHolder) holder), position); break; } } } @Override public int getItemViewType(int position) { if (position == getStatusesCount()) { return ITEM_VIEW_TYPE_LOAD_INDICATOR; } else if (isGapItem(position)) { return ITEM_VIEW_TYPE_GAP; } return ITEM_VIEW_TYPE_STATUS; } @Override public final int getItemCount() { return getStatusesCount() + (mLoadMoreIndicatorVisible ? 1 : 0); } @Override public final void onGapClick(ViewHolder holder, int position) { if (mStatusAdapterListener != null) { mStatusAdapterListener.onGapClick((GapViewHolder) holder, position); } } @Override public void onItemActionClick(ViewHolder holder, int id, int position) { if (mStatusAdapterListener != null) { mStatusAdapterListener.onStatusActionClick((StatusViewHolder) holder, id, position); } } @Override public void onItemMenuClick(ViewHolder holder, View menuView, int position) { if (mStatusAdapterListener != null) { mStatusAdapterListener.onStatusMenuClick((StatusViewHolder) holder, menuView, position); } } public void setListener(StatusAdapterListener listener) { mStatusAdapterListener = listener; } public void setShowAccountsColor(boolean showAccountsColor) { if (mShowAccountsColor == showAccountsColor) return; mShowAccountsColor = showAccountsColor; notifyDataSetChanged(); } protected abstract void bindStatus(StatusViewHolder holder, int position); public static interface StatusAdapterListener { void onGapClick(GapViewHolder holder, int position); void onMediaClick(StatusViewHolder holder, ParcelableMedia media, int position); void onStatusActionClick(StatusViewHolder holder, int id, int position); void onStatusClick(StatusViewHolder holder, int position); void onStatusMenuClick(StatusViewHolder holder, View menuView, int position); } }