org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter.java Source code

Java tutorial

Introduction

Here is the source code for org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter.java

Source

/*
 * Twidere - Twitter client for Android
 *
 *  Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
 *
 *  This program 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.
 *
 *  This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.mariotaku.twidere.adapter;

import android.content.Context;
import android.database.Cursor;
import android.support.annotation.Nullable;
import android.support.v4.widget.Space;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import org.apache.commons.lang3.ArrayUtils;
import org.mariotaku.library.objectcursor.ObjectCursor;
import org.mariotaku.microblog.library.twitter.model.Activity;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.iface.IActivitiesAdapter;
import org.mariotaku.twidere.fragment.CursorActivitiesFragment;
import org.mariotaku.twidere.fragment.UserFragment;
import org.mariotaku.twidere.model.ParcelableActivity;
import org.mariotaku.twidere.model.ParcelableActivityCursorIndices;
import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.util.ParcelableActivityUtils;
import org.mariotaku.twidere.util.IntentUtils;
import org.mariotaku.twidere.util.MediaLoadingHandler;
import org.mariotaku.twidere.util.OnLinkClickHandler;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.TwidereLinkify;
import org.mariotaku.twidere.view.holder.ActivityTitleSummaryViewHolder;
import org.mariotaku.twidere.view.holder.EmptyViewHolder;
import org.mariotaku.twidere.view.holder.GapViewHolder;
import org.mariotaku.twidere.view.holder.LoadIndicatorViewHolder;
import org.mariotaku.twidere.view.holder.StatusViewHolder;
import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder;

import java.lang.ref.WeakReference;
import java.util.List;

import static org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_NEW_DOCUMENT_API;

/**
 * Created by mariotaku on 15/1/3.
 */
public class ParcelableActivitiesAdapter extends LoadMoreSupportAdapter<RecyclerView.ViewHolder>
        implements IActivitiesAdapter<List<ParcelableActivity>> {

    public static final int ITEM_VIEW_TYPE_STUB = 0;
    public static final int ITEM_VIEW_TYPE_GAP = 1;
    public static final int ITEM_VIEW_TYPE_LOAD_INDICATOR = 2;
    public static final int ITEM_VIEW_TYPE_TITLE_SUMMARY = 3;
    public static final int ITEM_VIEW_TYPE_STATUS = 4;
    public static final int ITEM_VIEW_TYPE_EMPTY = 5;
    private final LayoutInflater mInflater;
    private final MediaLoadingHandler mLoadingHandler;
    private final int mCardBackgroundColor;
    private final DummyItemAdapter mStatusAdapterDelegate;
    private final EventListener mEventListener;
    private List<ParcelableActivity> mData;
    private final boolean mIsByFriends;
    private ActivityAdapterListener mActivityAdapterListener;
    private UserKey[] mFilteredUserIds;
    private boolean mFollowingOnly;
    private boolean mMentionsOnly;

    public ParcelableActivitiesAdapter(Context context, boolean byFriends) {
        super(context);
        mStatusAdapterDelegate = new DummyItemAdapter(context,
                new TwidereLinkify(new OnLinkClickHandler(context, null, mPreferences)), this);
        mCardBackgroundColor = ThemeUtils.getCardBackgroundColor(context,
                ThemeUtils.getThemeBackgroundOption(context), ThemeUtils.getUserThemeBackgroundAlpha(context));
        mInflater = LayoutInflater.from(context);
        mLoadingHandler = new MediaLoadingHandler(R.id.media_preview_progress);
        mEventListener = new EventListener(this);
        mStatusAdapterDelegate.updateOptions();
        mIsByFriends = byFriends;
    }

    @Override
    public boolean isGapItem(int adapterPosition) {
        int dataPosition = adapterPosition - getActivityStartIndex();
        final int activityCount = getActivityCount();
        if (dataPosition < 0 || dataPosition >= activityCount)
            return false;
        // Don't show gap if it's last item
        if (dataPosition == activityCount - 1) {
            return false;
        }
        if (mData instanceof ObjectCursor) {
            final Cursor cursor = ((ObjectCursor) mData).getCursor();
            if (!cursor.moveToPosition(dataPosition))
                return false;
            final ParcelableActivityCursorIndices indices = (ParcelableActivityCursorIndices) ((ObjectCursor) mData)
                    .getIndices();
            return cursor.getShort(indices.is_gap) == 1;
        }
        return mData.get(dataPosition).is_gap;
    }

    @Override
    public long getItemId(int adapterPosition) {
        int dataPosition = adapterPosition - getActivityStartIndex();
        if (dataPosition < 0 || dataPosition >= getActivityCount())
            return RecyclerView.NO_ID;
        if (mData instanceof ObjectCursor) {
            final Cursor cursor = ((ObjectCursor) mData).getCursor();
            if (!cursor.moveToPosition(dataPosition))
                return -1;
            final ParcelableActivityCursorIndices indices = (ParcelableActivityCursorIndices) ((ObjectCursor) mData)
                    .getIndices();
            final UserKey accountKey = UserKey.valueOf(cursor.getString(indices.account_key));
            final long timestamp = cursor.getLong(indices.timestamp);
            final long maxPosition = cursor.getLong(indices.max_position);
            final long minPosition = cursor.getLong(indices.min_position);
            return ParcelableActivity.calculateHashCode(accountKey, timestamp, maxPosition, minPosition);
        }
        return mData.get(dataPosition).hashCode();
    }

    @Nullable
    public String getActivityAction(int adapterPosition) {
        int dataPosition = adapterPosition - getActivityStartIndex();
        if (dataPosition < 0 || dataPosition >= getActivityCount())
            return null;
        if (mData instanceof ObjectCursor) {
            final Cursor cursor = ((ObjectCursor) mData).getCursor();
            if (!cursor.moveToPosition(dataPosition))
                return null;
            final ParcelableActivityCursorIndices indices = (ParcelableActivityCursorIndices) ((ObjectCursor) mData)
                    .getIndices();
            return cursor.getString(indices.action);
        }
        return mData.get(dataPosition).action;
    }

    public long getTimestamp(int adapterPosition) {
        int dataPosition = adapterPosition - getActivityStartIndex();
        if (dataPosition < 0 || dataPosition >= getActivityCount())
            return RecyclerView.NO_ID;
        if (mData instanceof ObjectCursor) {
            final Cursor cursor = ((ObjectCursor) mData).getCursor();
            if (!cursor.moveToPosition(dataPosition))
                return -1;
            final ParcelableActivityCursorIndices indices = (ParcelableActivityCursorIndices) ((ObjectCursor) mData)
                    .getIndices();
            return cursor.getLong(indices.timestamp);
        }
        return mData.get(dataPosition).timestamp;
    }

    @Override
    public ParcelableActivity getActivity(int adapterPosition) {
        int dataPosition = adapterPosition - getActivityStartIndex();
        if (dataPosition < 0 || dataPosition >= getActivityCount())
            return null;
        return mData.get(dataPosition);
    }

    @Override
    public int getActivityCount() {
        if (mData == null)
            return 0;
        return mData.size();
    }

    protected void onSetData(List<ParcelableActivity> data) {
        mData = data;
        notifyDataSetChanged();
    }

    protected void bindTitleSummaryViewHolder(ActivityTitleSummaryViewHolder holder, int position) {
        holder.displayActivity(getActivity(position), mIsByFriends);
    }

    public List<ParcelableActivity> getData() {
        return mData;
    }

    @Override
    public final void setData(List<ParcelableActivity> data) {
        if (data instanceof CursorActivitiesFragment.CursorActivitiesLoader.ActivityCursor) {
            mFilteredUserIds = ((CursorActivitiesFragment.CursorActivitiesLoader.ActivityCursor) data)
                    .getFilteredUserIds();
        }
        onSetData(data);
    }

    @Override
    public MediaLoadingHandler getMediaLoadingHandler() {
        return mLoadingHandler;
    }

    @Nullable
    @Override
    public ActivityEventListener getActivityEventListener() {
        return mEventListener;
    }

    @Nullable
    @Override
    public GapClickListener getGapClickListener() {
        return mEventListener;
    }

    @Override
    public int getProfileImageStyle() {
        return mStatusAdapterDelegate.getProfileImageStyle();
    }

    @Override
    public int getMediaPreviewStyle() {
        return mStatusAdapterDelegate.getMediaPreviewStyle();
    }

    @Override
    public float getTextSize() {
        return mStatusAdapterDelegate.getTextSize();
    }

    public boolean isNameFirst() {
        return mStatusAdapterDelegate.isNameFirst();
    }

    @Override
    public boolean isProfileImageEnabled() {
        return mStatusAdapterDelegate.isProfileImageEnabled();
    }

    @Override
    public boolean isShowAbsoluteTime() {
        return mStatusAdapterDelegate.isShowAbsoluteTime();
    }

    @Override
    public boolean shouldUseStarsForLikes() {
        return mStatusAdapterDelegate.shouldUseStarsForLikes();
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType) {
        case ITEM_VIEW_TYPE_STATUS: {
            final StatusViewHolder holder = ListParcelableStatusesAdapter
                    .createStatusViewHolder(mStatusAdapterDelegate, mInflater, parent);
            holder.setStatusClickListener(mEventListener);
            return holder;
        }
        case ITEM_VIEW_TYPE_TITLE_SUMMARY: {
            final View view = mInflater.inflate(R.layout.card_item_activity_summary_compact, parent, false);
            final ActivityTitleSummaryViewHolder holder = new ActivityTitleSummaryViewHolder(this, view);
            holder.setOnClickListeners();
            holder.setTextSize(getTextSize());
            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);
        }
        case ITEM_VIEW_TYPE_STUB: {
            final View view = mInflater.inflate(R.layout.list_item_two_line, parent, false);
            return new StubViewHolder(view);
        }
        case ITEM_VIEW_TYPE_EMPTY: {
            return new EmptyViewHolder(new Space(getContext()));
        }
        }
        throw new UnsupportedOperationException("Unsupported viewType " + viewType);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        switch (getItemViewType(position)) {
        case ITEM_VIEW_TYPE_STATUS: {
            final ParcelableActivity activity = getActivity(position);
            final ParcelableStatus status = ParcelableActivityUtils.getActivityStatus(activity);
            assert status != null;
            final IStatusViewHolder statusViewHolder = (IStatusViewHolder) holder;
            statusViewHolder.displayStatus(status, true, true);
            break;
        }
        case ITEM_VIEW_TYPE_TITLE_SUMMARY: {
            bindTitleSummaryViewHolder((ActivityTitleSummaryViewHolder) holder, position);
            break;
        }
        case ITEM_VIEW_TYPE_STUB: {
            ((StubViewHolder) holder).displayActivity(getActivity(position));
            break;
        }
        }
    }

    @Override
    public int getItemViewType(int position) {
        final ParcelableActivity activity = getActivity(position);
        if ((getLoadMoreIndicatorPosition() & IndicatorPosition.START) != 0 && position == 0) {
            return ITEM_VIEW_TYPE_LOAD_INDICATOR;
        } else if (position == getActivityCount()) {
            return ITEM_VIEW_TYPE_LOAD_INDICATOR;
        } else if (isGapItem(position)) {
            return ITEM_VIEW_TYPE_GAP;
        }
        final String action = getActivityAction(position);
        if (action == null)
            throw new NullPointerException();
        switch (action) {
        case Activity.Action.MENTION: {
            if (ArrayUtils.isEmpty(activity.target_object_statuses)) {
                return ITEM_VIEW_TYPE_STUB;
            }
            if (mFollowingOnly && !activity.status_user_following)
                return ITEM_VIEW_TYPE_EMPTY;
            return ITEM_VIEW_TYPE_STATUS;
        }
        case Activity.Action.REPLY: {
            if (ArrayUtils.isEmpty(activity.target_statuses)) {
                return ITEM_VIEW_TYPE_STUB;
            }
            if (mFollowingOnly && !activity.status_user_following)
                return ITEM_VIEW_TYPE_EMPTY;
            return ITEM_VIEW_TYPE_STATUS;
        }
        case Activity.Action.QUOTE: {
            if (ArrayUtils.isEmpty(activity.target_statuses)) {
                return ITEM_VIEW_TYPE_STUB;
            }
            if (mFollowingOnly && !activity.status_user_following)
                return ITEM_VIEW_TYPE_EMPTY;
            return ITEM_VIEW_TYPE_STATUS;
        }
        case Activity.Action.FOLLOW:
        case Activity.Action.FAVORITE:
        case Activity.Action.RETWEET:
        case Activity.Action.FAVORITED_RETWEET:
        case Activity.Action.RETWEETED_RETWEET:
        case Activity.Action.RETWEETED_MENTION:
        case Activity.Action.FAVORITED_MENTION:
        case Activity.Action.LIST_CREATED:
        case Activity.Action.LIST_MEMBER_ADDED:
        case Activity.Action.MEDIA_TAGGED:
        case Activity.Action.RETWEETED_MEDIA_TAGGED:
        case Activity.Action.FAVORITED_MEDIA_TAGGED:
        case Activity.Action.JOINED_TWITTER: {
            if (mMentionsOnly)
                return ITEM_VIEW_TYPE_EMPTY;
            ParcelableActivityUtils.initAfterFilteredSourceIds(activity, mFilteredUserIds, mFollowingOnly);
            if (ArrayUtils.isEmpty(activity.after_filtered_source_ids)) {
                return ITEM_VIEW_TYPE_EMPTY;
            }
            return ITEM_VIEW_TYPE_TITLE_SUMMARY;
        }
        }
        return ITEM_VIEW_TYPE_STUB;
    }

    public void setFollowingOnly(boolean followingOnly) {
        mFollowingOnly = followingOnly;
        notifyDataSetChanged();
    }

    public void setMentionsOnly(boolean mentionsOnly) {
        mMentionsOnly = mentionsOnly;
        notifyDataSetChanged();
    }

    @Override
    public final int getItemCount() {
        final int position = getLoadMoreIndicatorPosition();
        int count = 0;
        if ((position & IndicatorPosition.START) != 0) {
            count += 1;
        }
        count += getActivityCount();
        if ((position & IndicatorPosition.END) != 0) {
            count += 1;
        }
        return count;
    }

    public void setListener(ActivityAdapterListener listener) {
        mActivityAdapterListener = listener;
    }

    @Override
    public boolean isMediaPreviewEnabled() {
        return mStatusAdapterDelegate.isMediaPreviewEnabled();
    }

    @Override
    public boolean shouldShowAccountsColor() {
        return mStatusAdapterDelegate.shouldShowAccountsColor();
    }

    public void setShowAccountsColor(boolean showAccountsColor) {
        mStatusAdapterDelegate.setShouldShowAccountsColor(showAccountsColor);
        notifyDataSetChanged();
    }

    public boolean isActivity(int position) {
        return position < getActivityCount();
    }

    public int getActivityStartIndex() {
        final int position = getLoadMoreIndicatorPosition();
        int start = 0;
        if ((position & IndicatorPosition.START) != 0) {
            start += 1;
        }
        return start;
    }

    public interface ActivityAdapterListener {
        void onGapClick(GapViewHolder holder, int position);

        void onActivityClick(ActivityTitleSummaryViewHolder holder, int position);

        void onStatusActionClick(IStatusViewHolder holder, int id, int position);

        void onStatusMenuClick(IStatusViewHolder holder, View menuView, int position);

        void onMediaClick(IStatusViewHolder holder, View view, ParcelableMedia media, int position);

        void onStatusClick(IStatusViewHolder holder, int position);

    }

    static class StubViewHolder extends RecyclerView.ViewHolder {

        final TextView text1, text2;

        public StubViewHolder(View itemView) {
            super(itemView);
            text1 = (TextView) itemView.findViewById(android.R.id.text1);
            text2 = (TextView) itemView.findViewById(android.R.id.text2);
        }

        public void displayActivity(ParcelableActivity activity) {
            text1.setText(
                    text1.getResources().getString(R.string.unsupported_activity_action_title, activity.action));
            text2.setText(R.string.unsupported_activity_action_summary);
        }
    }

    static class EventListener
            implements IStatusViewHolder.StatusClickListener, GapClickListener, ActivityEventListener {

        final WeakReference<ParcelableActivitiesAdapter> adapterRef;

        EventListener(ParcelableActivitiesAdapter adapter) {
            adapterRef = new WeakReference<>(adapter);
        }

        @Override
        public final void onGapClick(GapViewHolder holder, int position) {
            final ParcelableActivitiesAdapter adapter = adapterRef.get();
            if (adapter == null)
                return;
            if (adapter.mActivityAdapterListener != null) {
                adapter.mActivityAdapterListener.onGapClick(holder, position);
            }
        }

        @Override
        public final void onItemActionClick(RecyclerView.ViewHolder holder, int id, int position) {
            final ParcelableActivitiesAdapter adapter = adapterRef.get();
            if (adapter == null)
                return;
            if (adapter.mActivityAdapterListener != null) {
                adapter.mActivityAdapterListener.onStatusActionClick((IStatusViewHolder) holder, id, position);
            }
        }

        @Override
        public boolean onStatusLongClick(IStatusViewHolder holder, int position) {
            return false;
        }

        @Override
        public void onUserProfileClick(IStatusViewHolder holder, int position) {
            final ParcelableActivitiesAdapter adapter = adapterRef.get();
            if (adapter == null)
                return;
            final Context context = adapter.getContext();
            final ParcelableActivity activity = adapter.getActivity(position);
            final ParcelableStatus status = ParcelableActivityUtils.getActivityStatus(activity);
            assert status != null;
            IntentUtils.openUserProfile(context, status.account_key, status.user_key, status.user_screen_name, null,
                    adapter.mPreferences.getBoolean(KEY_NEW_DOCUMENT_API), UserFragment.Referral.TIMELINE_STATUS);
        }

        @Override
        public void onStatusClick(IStatusViewHolder holder, int position) {
            final ParcelableActivitiesAdapter adapter = adapterRef.get();
            if (adapter == null)
                return;
            if (adapter.mActivityAdapterListener != null) {
                adapter.mActivityAdapterListener.onStatusClick(holder, position);
            }
        }

        @Override
        public void onMediaClick(IStatusViewHolder holder, View view, ParcelableMedia media, int statusPosition) {
            final ParcelableActivitiesAdapter adapter = adapterRef.get();
            if (adapter == null)
                return;
            if (adapter.mActivityAdapterListener != null) {
                adapter.mActivityAdapterListener.onMediaClick(holder, view, media, statusPosition);
            }
        }

        @Override
        public void onActivityClick(ActivityTitleSummaryViewHolder holder, int position) {
            final ParcelableActivitiesAdapter adapter = adapterRef.get();
            if (adapter == null)
                return;
            if (adapter.mActivityAdapterListener == null)
                return;
            adapter.mActivityAdapterListener.onActivityClick(holder, position);
        }

        @Override
        public final void onItemMenuClick(RecyclerView.ViewHolder holder, View menuView, int position) {
            final ParcelableActivitiesAdapter adapter = adapterRef.get();
            if (adapter == null)
                return;
            if (adapter.mActivityAdapterListener != null) {
                adapter.mActivityAdapterListener.onStatusMenuClick((StatusViewHolder) holder, menuView, position);
            }
        }
    }
}