migrating users list to RecyclerView
This commit is contained in:
parent
162ac1af42
commit
eb82d1eee7
|
@ -21,6 +21,7 @@ package org.mariotaku.twidere.adapter;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.util.Pair;
|
||||
import android.support.v7.widget.CardView;
|
||||
|
@ -40,7 +41,7 @@ import org.mariotaku.twidere.model.ParcelableActivity;
|
|||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.ImageLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
|
@ -69,7 +70,7 @@ public abstract class AbsActivitiesAdapter<Data> extends Adapter<ViewHolder> imp
|
|||
private final Context mContext;
|
||||
private final LayoutInflater mInflater;
|
||||
private final MediaLoaderWrapper mImageLoader;
|
||||
private final ImageLoadingHandler mLoadingHandler;
|
||||
private final MediaLoadingHandler mLoadingHandler;
|
||||
private final AsyncTwitterWrapper mTwitterWrapper;
|
||||
private final int mCardBackgroundColor;
|
||||
private final int mTextSize;
|
||||
|
@ -90,7 +91,7 @@ public abstract class AbsActivitiesAdapter<Data> extends Adapter<ViewHolder> imp
|
|||
mCardBackgroundColor = ThemeUtils.getCardBackgroundColor(context);
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mImageLoader = app.getMediaLoaderWrapper();
|
||||
mLoadingHandler = new ImageLoadingHandler(R.id.media_preview_progress);
|
||||
mLoadingHandler = new MediaLoadingHandler(R.id.media_preview_progress);
|
||||
mTwitterWrapper = app.getTwitterWrapper();
|
||||
final SharedPreferencesWrapper preferences = SharedPreferencesWrapper.getInstance(context,
|
||||
SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
|
@ -115,7 +116,7 @@ public abstract class AbsActivitiesAdapter<Data> extends Adapter<ViewHolder> imp
|
|||
public abstract void setData(Data data);
|
||||
|
||||
@Override
|
||||
public MediaLoaderWrapper getImageLoader() {
|
||||
public MediaLoaderWrapper getMediaLoader() {
|
||||
return mImageLoader;
|
||||
}
|
||||
|
||||
|
@ -125,7 +126,7 @@ public abstract class AbsActivitiesAdapter<Data> extends Adapter<ViewHolder> imp
|
|||
}
|
||||
|
||||
@Override
|
||||
public ImageLoadingHandler getImageLoadingHandler() {
|
||||
public MediaLoadingHandler getMediaLoadingHandler() {
|
||||
return mLoadingHandler;
|
||||
}
|
||||
|
||||
|
@ -139,6 +140,7 @@ public abstract class AbsActivitiesAdapter<Data> extends Adapter<ViewHolder> imp
|
|||
return mMediaPreviewStyle;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AsyncTwitterWrapper getTwitterWrapper() {
|
||||
return mTwitterWrapper;
|
||||
|
@ -187,7 +189,6 @@ public abstract class AbsActivitiesAdapter<Data> extends Adapter<ViewHolder> imp
|
|||
return mNameFirst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProfileImageEnabled() {
|
||||
return mDisplayProfileImage;
|
||||
}
|
||||
|
@ -304,6 +305,11 @@ public abstract class AbsActivitiesAdapter<Data> extends Adapter<ViewHolder> imp
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStatusLongClick(StatusViewHolder holder, int position) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (position == getActivityCount()) {
|
||||
|
|
|
@ -2,10 +2,10 @@ package org.mariotaku.twidere.adapter;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
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;
|
||||
|
@ -19,8 +19,8 @@ import org.mariotaku.twidere.fragment.support.UserFragment;
|
|||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.ImageLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.MediaLoadingHandler;
|
||||
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
|
||||
import org.mariotaku.twidere.util.StatusAdapterLinkClickHandler;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
|
@ -36,17 +36,15 @@ import org.mariotaku.twidere.view.holder.StatusViewHolder;
|
|||
/**
|
||||
* Created by mariotaku on 14/11/19.
|
||||
*/
|
||||
public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implements Constants,
|
||||
public abstract class AbsStatusesAdapter<D> extends LoadMoreSupportAdapter<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 MediaLoaderWrapper mMediaLoader;
|
||||
private final MediaLoadingHandler mLoadingHandler;
|
||||
private final AsyncTwitterWrapper mTwitterWrapper;
|
||||
private final TwidereLinkify mLinkify;
|
||||
|
||||
|
@ -68,8 +66,6 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
|
|||
private final boolean mSensitiveContentEnabled;
|
||||
private final boolean mHideCardActions;
|
||||
|
||||
private boolean mLoadMoreSupported;
|
||||
private boolean mLoadMoreIndicatorVisible;
|
||||
private boolean mShowInReplyTo;
|
||||
private boolean mShowAccountsColor;
|
||||
|
||||
|
@ -78,8 +74,8 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
|
|||
final TwidereApplication app = TwidereApplication.getInstance(context);
|
||||
mCardBackgroundColor = ThemeUtils.getCardBackgroundColor(context);
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mImageLoader = app.getMediaLoaderWrapper();
|
||||
mLoadingHandler = new ImageLoadingHandler(R.id.media_preview_progress);
|
||||
mMediaLoader = app.getMediaLoaderWrapper();
|
||||
mLoadingHandler = new MediaLoadingHandler(R.id.media_preview_progress);
|
||||
mTwitterWrapper = app.getTwitterWrapper();
|
||||
final SharedPreferencesWrapper preferences = SharedPreferencesWrapper.getInstance(context,
|
||||
SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
|
@ -107,8 +103,8 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
|
|||
}
|
||||
|
||||
@Override
|
||||
public final MediaLoaderWrapper getImageLoader() {
|
||||
return mImageLoader;
|
||||
public final MediaLoaderWrapper getMediaLoader() {
|
||||
return mMediaLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -117,7 +113,7 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
|
|||
}
|
||||
|
||||
@Override
|
||||
public final ImageLoadingHandler getImageLoadingHandler() {
|
||||
public final MediaLoadingHandler getMediaLoadingHandler() {
|
||||
return mLoadingHandler;
|
||||
}
|
||||
|
||||
|
@ -131,6 +127,7 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
|
|||
return mMediaPreviewStyle;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public final AsyncTwitterWrapper getTwitterWrapper() {
|
||||
return mTwitterWrapper;
|
||||
|
@ -141,32 +138,6 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
|
|||
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 TwidereLinkify getTwidereLinkify() {
|
||||
return mLinkify;
|
||||
|
@ -203,18 +174,21 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
|
|||
}
|
||||
|
||||
@Override
|
||||
public final void onStatusClick(StatusViewHolder holder, int position) {
|
||||
if (mStatusAdapterListener != null) {
|
||||
mStatusAdapterListener.onStatusClick(holder, position);
|
||||
public boolean onStatusLongClick(StatusViewHolder holder, int position) {
|
||||
return mStatusAdapterListener != null && mStatusAdapterListener.onStatusLongClick(holder, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onStatusClick(StatusViewHolder holder, int position) {
|
||||
if (mStatusAdapterListener == null) return;
|
||||
mStatusAdapterListener.onStatusClick(holder, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaClick(StatusViewHolder holder, final ParcelableMedia media, int position) {
|
||||
if (mStatusAdapterListener != null) {
|
||||
if (mStatusAdapterListener == null) return;
|
||||
mStatusAdapterListener.onMediaClick(holder, media, position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserProfileClick(final StatusViewHolder holder, final int position) {
|
||||
|
@ -300,29 +274,26 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
|
|||
|
||||
@Override
|
||||
public final int getItemCount() {
|
||||
return getStatusesCount() + (mLoadMoreIndicatorVisible ? 1 : 0);
|
||||
return getStatusesCount() + (isLoadMoreIndicatorVisible() ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onGapClick(ViewHolder holder, int position) {
|
||||
if (mStatusAdapterListener != null) {
|
||||
if (mStatusAdapterListener == null) return;
|
||||
mStatusAdapterListener.onGapClick((GapViewHolder) holder, position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemActionClick(ViewHolder holder, int id, int position) {
|
||||
if (mStatusAdapterListener != null) {
|
||||
if (mStatusAdapterListener == null) return;
|
||||
mStatusAdapterListener.onStatusActionClick((StatusViewHolder) holder, id, position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemMenuClick(ViewHolder holder, View menuView, int position) {
|
||||
if (mStatusAdapterListener != null) {
|
||||
if (mStatusAdapterListener == null) return;
|
||||
mStatusAdapterListener.onStatusMenuClick((StatusViewHolder) holder, menuView, position);
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener(StatusAdapterListener listener) {
|
||||
mStatusAdapterListener = listener;
|
||||
|
@ -345,6 +316,8 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
|
|||
|
||||
void onStatusClick(StatusViewHolder holder, int position);
|
||||
|
||||
boolean onStatusLongClick(StatusViewHolder holder, int position);
|
||||
|
||||
void onStatusMenuClick(StatusViewHolder holder, View menuView, int position);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* 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.support.annotation.NonNull;
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.adapter.iface.IUsersAdapter;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.view.holder.LoadIndicatorViewHolder;
|
||||
import org.mariotaku.twidere.view.holder.UserViewHolder;
|
||||
|
||||
public abstract class AbsUsersAdapter<D> extends LoadMoreSupportAdapter<ViewHolder> implements Constants,
|
||||
IUsersAdapter<D> {
|
||||
|
||||
public static final int ITEM_VIEW_TYPE_USER = 2;
|
||||
|
||||
private final Context mContext;
|
||||
private final LayoutInflater mInflater;
|
||||
private final MediaLoaderWrapper mMediaLoader;
|
||||
|
||||
private final int mCardBackgroundColor;
|
||||
private final boolean mCompactCards;
|
||||
private final int mProfileImageStyle;
|
||||
private final int mTextSize;
|
||||
private final AsyncTwitterWrapper mTwitterWrapper;
|
||||
private final boolean mDisplayProfileImage;
|
||||
|
||||
public AbsUsersAdapter(final Context context, final boolean compact) {
|
||||
final TwidereApplication app = TwidereApplication.getInstance(context);
|
||||
mContext = context;
|
||||
mCardBackgroundColor = ThemeUtils.getCardBackgroundColor(context);
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mMediaLoader = app.getMediaLoaderWrapper();
|
||||
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));
|
||||
mProfileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null));
|
||||
mDisplayProfileImage = preferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true);
|
||||
mCompactCards = compact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProfileImageStyle() {
|
||||
return mProfileImageStyle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getTextSize() {
|
||||
return mTextSize;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AsyncTwitterWrapper getTwitterWrapper() {
|
||||
return mTwitterWrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProfileImageEnabled() {
|
||||
return mDisplayProfileImage;
|
||||
}
|
||||
|
||||
public abstract D getData();
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
switch (viewType) {
|
||||
case ITEM_VIEW_TYPE_USER: {
|
||||
final View view;
|
||||
if (mCompactCards) {
|
||||
view = mInflater.inflate(R.layout.card_item_user_compact, parent, false);
|
||||
// final View itemContent = view.findViewById(R.id.item_content);
|
||||
// itemContent.setBackgroundColor(mCardBackgroundColor);
|
||||
} else {
|
||||
view = mInflater.inflate(R.layout.card_item_user, parent, false);
|
||||
// final CardView cardView = (CardView) view.findViewById(R.id.card);
|
||||
// cardView.setCardBackgroundColor(mCardBackgroundColor);
|
||||
}
|
||||
final UserViewHolder holder = new UserViewHolder(this, view);
|
||||
// holder.setOnClickListeners();
|
||||
// holder.setupViewOptions();
|
||||
return holder;
|
||||
}
|
||||
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_USER: {
|
||||
bindStatus(((UserViewHolder) holder), position);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isUser(int position) {
|
||||
return position < getUsersCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (position == getUsersCount()) {
|
||||
return ITEM_VIEW_TYPE_LOAD_INDICATOR;
|
||||
}
|
||||
return ITEM_VIEW_TYPE_USER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldShowAccountsColor() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaLoaderWrapper getMediaLoader() {
|
||||
return mMediaLoader;
|
||||
}
|
||||
|
||||
protected abstract void bindStatus(UserViewHolder holder, int position);
|
||||
|
||||
}
|
|
@ -34,7 +34,7 @@ import org.mariotaku.twidere.model.DraftItem;
|
|||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.model.ParcelableMediaUpdate;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts;
|
||||
import org.mariotaku.twidere.util.ImageLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
|
||||
import org.mariotaku.twidere.util.TwidereArrayUtils;
|
||||
|
@ -46,7 +46,7 @@ import static org.mariotaku.twidere.util.Utils.getAccountColors;
|
|||
public class DraftsAdapter extends SimpleCursorAdapter implements Constants {
|
||||
|
||||
private final MediaLoaderWrapper mImageLoader;
|
||||
private final ImageLoadingHandler mImageLoadingHandler;
|
||||
private final MediaLoadingHandler mMediaLoadingHandler;
|
||||
private final int mMediaPreviewStyle;
|
||||
|
||||
private float mTextSize;
|
||||
|
@ -55,7 +55,7 @@ public class DraftsAdapter extends SimpleCursorAdapter implements Constants {
|
|||
public DraftsAdapter(final Context context) {
|
||||
super(context, R.layout.list_item_draft, null, new String[0], new int[0], 0);
|
||||
mImageLoader = TwidereApplication.getInstance(context).getMediaLoaderWrapper();
|
||||
mImageLoadingHandler = new ImageLoadingHandler(R.id.media_preview_progress);
|
||||
mMediaLoadingHandler = new MediaLoadingHandler(R.id.media_preview_progress);
|
||||
final SharedPreferencesWrapper preferences = SharedPreferencesWrapper.getInstance(context,
|
||||
SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
mMediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null));
|
||||
|
@ -74,7 +74,7 @@ public class DraftsAdapter extends SimpleCursorAdapter implements Constants {
|
|||
if (actionType == Drafts.ACTION_UPDATE_STATUS) {
|
||||
final ParcelableMedia[] media = ParcelableMedia.fromMediaUpdates(mediaUpdates);
|
||||
holder.media_preview_container.setVisibility(View.VISIBLE);
|
||||
holder.media_preview_container.displayMedia(media, mImageLoader, -1L, null, mImageLoadingHandler);
|
||||
holder.media_preview_container.displayMedia(media, mImageLoader, -1L, null, mMediaLoadingHandler);
|
||||
} else {
|
||||
holder.media_preview_container.setVisibility(View.GONE);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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.support.v7.widget.RecyclerView.Adapter;
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
|
||||
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/16.
|
||||
*/
|
||||
public abstract class LoadMoreSupportAdapter<VH extends ViewHolder> extends Adapter<VH>
|
||||
implements ILoadMoreSupportAdapter {
|
||||
|
||||
private boolean mLoadMoreSupported;
|
||||
private boolean mLoadMoreIndicatorVisible;
|
||||
|
||||
@Override
|
||||
public final boolean isLoadMoreIndicatorVisible() {
|
||||
return mLoadMoreIndicatorVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setLoadMoreIndicatorVisible(boolean enabled) {
|
||||
if (mLoadMoreIndicatorVisible == enabled) return;
|
||||
mLoadMoreIndicatorVisible = enabled && mLoadMoreSupported;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isLoadMoreSupported() {
|
||||
return mLoadMoreSupported;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setLoadMoreSupported(boolean supported) {
|
||||
mLoadMoreSupported = supported;
|
||||
if (!supported) {
|
||||
mLoadMoreIndicatorVisible = false;
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
}
|
|
@ -28,7 +28,7 @@ import android.widget.ImageView;
|
|||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.util.ImageLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
|
||||
import java.util.Collection;
|
||||
|
@ -37,7 +37,7 @@ public class MediaPreviewAdapter extends ArrayAdapter<String> implements Constan
|
|||
|
||||
private final MediaLoaderWrapper mImageLoader;
|
||||
private final SharedPreferences mPreferences;
|
||||
private final ImageLoadingHandler mImageLoadingHandler;
|
||||
private final MediaLoadingHandler mMediaLoadingHandler;
|
||||
|
||||
private boolean mIsPossiblySensitive;
|
||||
|
||||
|
@ -45,7 +45,7 @@ public class MediaPreviewAdapter extends ArrayAdapter<String> implements Constan
|
|||
super(context, R.layout.gallery_item_image_preview);
|
||||
mImageLoader = ((TwidereApplication) context.getApplicationContext()).getMediaLoaderWrapper();
|
||||
mPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
mImageLoadingHandler = new ImageLoadingHandler();
|
||||
mMediaLoadingHandler = new MediaLoadingHandler();
|
||||
}
|
||||
|
||||
public void addAll(final Collection<String> data, final boolean is_possibly_sensitive) {
|
||||
|
@ -63,9 +63,9 @@ public class MediaPreviewAdapter extends ArrayAdapter<String> implements Constan
|
|||
view.findViewById(R.id.media_preview_progress).setVisibility(View.GONE);
|
||||
image_view.setBackgroundResource(R.drawable.image_preview_nsfw);
|
||||
mImageLoader.cancelDisplayTask(image_view);
|
||||
} else if (!link.equals(mImageLoadingHandler.getLoadingUri(image_view))) {
|
||||
} else if (!link.equals(mMediaLoadingHandler.getLoadingUri(image_view))) {
|
||||
image_view.setBackgroundResource(0);
|
||||
mImageLoader.displayPreviewImage(image_view, link, mImageLoadingHandler);
|
||||
mImageLoader.displayPreviewImage(image_view, link, mMediaLoadingHandler);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ import org.mariotaku.twidere.app.TwidereApplication;
|
|||
import org.mariotaku.twidere.model.ParcelableDirectMessage;
|
||||
import org.mariotaku.twidere.model.ParcelableDirectMessage.CursorIndices;
|
||||
import org.mariotaku.twidere.util.DirectMessageOnLinkClickHandler;
|
||||
import org.mariotaku.twidere.util.ImageLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.MultiSelectManager;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
|
@ -61,7 +61,7 @@ public class MessageConversationAdapter extends Adapter<ViewHolder>
|
|||
private final LayoutInflater mInflater;
|
||||
private final MediaLoaderWrapper mImageLoader;
|
||||
private final MultiSelectManager mMultiSelectManager;
|
||||
private final ImageLoadingHandler mImageLoadingHandler;
|
||||
private final MediaLoadingHandler mMediaLoadingHandler;
|
||||
|
||||
private Cursor mCursor;
|
||||
private CursorIndices mIndices;
|
||||
|
@ -74,7 +74,7 @@ public class MessageConversationAdapter extends Adapter<ViewHolder>
|
|||
mLinkify = new TwidereLinkify(new DirectMessageOnLinkClickHandler(context, null));
|
||||
mMultiSelectManager = app.getMultiSelectManager();
|
||||
mImageLoader = app.getMediaLoaderWrapper();
|
||||
mImageLoadingHandler = new ImageLoadingHandler(R.id.media_preview_progress);
|
||||
mMediaLoadingHandler = new MediaLoadingHandler(R.id.media_preview_progress);
|
||||
mIncomingMessageColor = ThemeUtils.getUserAccentColor(context);
|
||||
mOutgoingMessageColor = ThemeUtils.getCardBackgroundColor(context);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import android.content.Context;
|
|||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.database.Cursor;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.RecyclerView.Adapter;
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -37,7 +38,6 @@ import org.mariotaku.twidere.app.TwidereApplication;
|
|||
import org.mariotaku.twidere.model.StringLongPair;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.ConversationEntries;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.ImageLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.MultiSelectManager;
|
||||
import org.mariotaku.twidere.util.ReadStateManager;
|
||||
|
@ -62,6 +62,8 @@ public class MessageEntriesAdapter extends Adapter<ViewHolder> implements Consta
|
|||
private final int mMediaPreviewStyle;
|
||||
private final ReadStateManager mReadStateManager;
|
||||
private final OnSharedPreferenceChangeListener mReadStateChangeListener;
|
||||
private final boolean mDisplayProfileImage;
|
||||
private final AsyncTwitterWrapper mTwitterWrapper;
|
||||
private boolean mLoadMoreSupported;
|
||||
private boolean mLoadMoreIndicatorVisible;
|
||||
private Cursor mCursor;
|
||||
|
@ -74,10 +76,12 @@ public class MessageEntriesAdapter extends Adapter<ViewHolder> implements Consta
|
|||
final TwidereApplication app = TwidereApplication.getInstance(context);
|
||||
mMultiSelectManager = app.getMultiSelectManager();
|
||||
mImageLoader = app.getMediaLoaderWrapper();
|
||||
mTwitterWrapper = app.getTwitterWrapper();
|
||||
final SharedPreferencesWrapper preferences = SharedPreferencesWrapper.getInstance(context,
|
||||
SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
mProfileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null));
|
||||
mMediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null));
|
||||
mDisplayProfileImage = preferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true);
|
||||
mTextSize = preferences.getInt(KEY_TEXT_SIZE, context.getResources().getInteger(R.integer.default_text_size));
|
||||
mReadStateManager = app.getReadStateManager();
|
||||
mReadStateChangeListener = new OnSharedPreferenceChangeListener() {
|
||||
|
@ -89,58 +93,39 @@ public class MessageEntriesAdapter extends Adapter<ViewHolder> implements Consta
|
|||
};
|
||||
}
|
||||
|
||||
public void onUserProfileClick(int position) {
|
||||
mListener.onUserClick(position, getEntry(position));
|
||||
}
|
||||
|
||||
public void updateReadState() {
|
||||
mPositionPairs = mReadStateManager.getPositionPairs(TAB_TYPE_DIRECT_MESSAGES);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public DirectMessageEntry getEntry(final int position) {
|
||||
final Cursor c = mCursor;
|
||||
if (c == null || c.isClosed() || !c.moveToPosition(position)) return null;
|
||||
return new DirectMessageEntry(c);
|
||||
}
|
||||
|
||||
public MediaLoaderWrapper getImageLoader() {
|
||||
return mImageLoader;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageLoadingHandler getImageLoadingHandler() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProfileImageStyle() {
|
||||
return mProfileImageStyle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMediaPreviewStyle() {
|
||||
return mMediaPreviewStyle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncTwitterWrapper getTwitterWrapper() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getTextSize() {
|
||||
return mTextSize;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AsyncTwitterWrapper getTwitterWrapper() {
|
||||
return mTwitterWrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReadStateChanged() {
|
||||
public boolean isProfileImageEnabled() {
|
||||
return mDisplayProfileImage;
|
||||
}
|
||||
|
||||
public DirectMessageEntry getEntry(final int position) {
|
||||
final Cursor c = mCursor;
|
||||
if (c == null || c.isClosed() || !c.moveToPosition(position)) return null;
|
||||
return new DirectMessageEntry(c);
|
||||
}
|
||||
|
||||
public MediaLoaderWrapper getMediaLoader() {
|
||||
return mImageLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -148,6 +133,13 @@ public class MessageEntriesAdapter extends Adapter<ViewHolder> implements Consta
|
|||
return mLoadMoreIndicatorVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoadMoreIndicatorVisible(boolean enabled) {
|
||||
if (mLoadMoreIndicatorVisible == enabled) return;
|
||||
mLoadMoreIndicatorVisible = enabled && mLoadMoreSupported;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoadMoreSupported() {
|
||||
return mLoadMoreSupported;
|
||||
|
@ -162,24 +154,6 @@ public class MessageEntriesAdapter extends Adapter<ViewHolder> implements Consta
|
|||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoadMoreIndicatorVisible(boolean enabled) {
|
||||
if (mLoadMoreIndicatorVisible == enabled) return;
|
||||
mLoadMoreIndicatorVisible = enabled && mLoadMoreSupported;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isGapItem(int position) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGapClick(ViewHolder holder, int position) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(final View view) {
|
||||
// if (mMultiSelectManager.isActive()) return;
|
||||
|
@ -226,18 +200,6 @@ public class MessageEntriesAdapter extends Adapter<ViewHolder> implements Consta
|
|||
}
|
||||
}
|
||||
|
||||
private boolean isUnread(Cursor c) {
|
||||
if (mPositionPairs == null) return true;
|
||||
final long accountId = c.getLong(ConversationEntries.IDX_ACCOUNT_ID);
|
||||
final long conversationId = c.getLong(ConversationEntries.IDX_CONVERSATION_ID);
|
||||
final long messageId = c.getLong(ConversationEntries.IDX_MESSAGE_ID);
|
||||
final String key = accountId + "-" + conversationId;
|
||||
for (StringLongPair pair : mPositionPairs) {
|
||||
if (key.equals(pair.getKey())) return messageId > pair.getValue();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (position == getMessagesCount()) {
|
||||
|
@ -251,21 +213,20 @@ public class MessageEntriesAdapter extends Adapter<ViewHolder> implements Consta
|
|||
return getMessagesCount() + (mLoadMoreIndicatorVisible ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemActionClick(ViewHolder holder, int id, int position) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemMenuClick(ViewHolder holder, View menuView, int position) {
|
||||
|
||||
}
|
||||
|
||||
public void onMessageClick(int position) {
|
||||
if (mListener == null) return;
|
||||
mListener.onEntryClick(position, getEntry(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReadStateChanged() {
|
||||
|
||||
}
|
||||
|
||||
public void onUserProfileClick(int position) {
|
||||
mListener.onUserClick(position, getEntry(position));
|
||||
}
|
||||
|
||||
public void setCursor(Cursor cursor) {
|
||||
mCursor = cursor;
|
||||
mReadStateManager.unregisterOnSharedPreferenceChangeListener(mReadStateChangeListener);
|
||||
|
@ -280,12 +241,29 @@ public class MessageEntriesAdapter extends Adapter<ViewHolder> implements Consta
|
|||
mListener = listener;
|
||||
}
|
||||
|
||||
public void updateReadState() {
|
||||
mPositionPairs = mReadStateManager.getPositionPairs(TAB_TYPE_DIRECT_MESSAGES);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private int getMessagesCount() {
|
||||
final Cursor c = mCursor;
|
||||
if (c == null || c.isClosed()) return 0;
|
||||
return c.getCount();
|
||||
}
|
||||
|
||||
private boolean isUnread(Cursor c) {
|
||||
if (mPositionPairs == null) return true;
|
||||
final long accountId = c.getLong(ConversationEntries.IDX_ACCOUNT_ID);
|
||||
final long conversationId = c.getLong(ConversationEntries.IDX_CONVERSATION_ID);
|
||||
final long messageId = c.getLong(ConversationEntries.IDX_MESSAGE_ID);
|
||||
final String key = accountId + "-" + conversationId;
|
||||
for (StringLongPair pair : mPositionPairs) {
|
||||
if (key.equals(pair.getKey())) return messageId > pair.getValue();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public interface MessageEntriesAdapterListener {
|
||||
void onEntryClick(int position, DirectMessageEntry entry);
|
||||
|
||||
|
|
|
@ -20,128 +20,57 @@
|
|||
package org.mariotaku.twidere.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.adapter.iface.IBaseCardAdapter;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.model.ParcelableUser;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.MultiSelectManager;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.view.holder.UserViewListHolder;
|
||||
import org.mariotaku.twidere.view.holder.UserViewHolder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.mariotaku.twidere.util.UserColorNameUtils.getUserColor;
|
||||
import static org.mariotaku.twidere.util.UserColorNameUtils.getUserNickname;
|
||||
import static org.mariotaku.twidere.util.Utils.configBaseCardAdapter;
|
||||
import static org.mariotaku.twidere.util.Utils.getAccountColor;
|
||||
import static org.mariotaku.twidere.util.Utils.getLocalizedNumber;
|
||||
import static org.mariotaku.twidere.util.Utils.getUserTypeIconRes;
|
||||
public class ParcelableUsersAdapter extends AbsUsersAdapter<List<ParcelableUser>> {
|
||||
|
||||
public class ParcelableUsersAdapter extends BaseArrayAdapter<ParcelableUser> implements IBaseCardAdapter {
|
||||
private List<ParcelableUser> mData;
|
||||
|
||||
private final MediaLoaderWrapper mProfileImageLoader;
|
||||
private final MultiSelectManager mMultiSelectManager;
|
||||
private final Context mContext;
|
||||
|
||||
private final Locale mLocale;
|
||||
|
||||
public ParcelableUsersAdapter(final Context context) {
|
||||
this(context, Utils.isCompactCards(context));
|
||||
}
|
||||
|
||||
public ParcelableUsersAdapter(final Context context, final boolean compactCards) {
|
||||
super(context, getItemResource(compactCards));
|
||||
mContext = context;
|
||||
mLocale = context.getResources().getConfiguration().locale;
|
||||
final TwidereApplication app = TwidereApplication.getInstance(context);
|
||||
mProfileImageLoader = app.getMediaLoaderWrapper();
|
||||
mMultiSelectManager = app.getMultiSelectManager();
|
||||
configBaseCardAdapter(context, this);
|
||||
public ParcelableUsersAdapter(Context context, boolean compact) {
|
||||
super(context, compact);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(final int position) {
|
||||
return getItem(position) != null ? getItem(position).id : -1;
|
||||
public List<ParcelableUser> getData() {
|
||||
return mData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final int position, final View convertView, final ViewGroup parent) {
|
||||
final View view = super.getView(position, convertView, parent);
|
||||
final Object tag = view.getTag();
|
||||
final UserViewListHolder holder;
|
||||
if (tag instanceof UserViewListHolder) {
|
||||
holder = (UserViewListHolder) tag;
|
||||
} else {
|
||||
holder = new UserViewListHolder(view);
|
||||
// holder.content.setOnOverflowIconClickListener(this);
|
||||
view.setTag(holder);
|
||||
public void setData(List<ParcelableUser> data) {
|
||||
mData = data;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
holder.position = position;
|
||||
|
||||
final ParcelableUser user = getItem(position);
|
||||
|
||||
final boolean showAccountColor = isShowAccountColor();
|
||||
|
||||
holder.setAccountColorEnabled(showAccountColor);
|
||||
|
||||
if (showAccountColor) {
|
||||
holder.setAccountColor(getAccountColor(mContext, user.account_id));
|
||||
@Override
|
||||
protected void bindStatus(UserViewHolder holder, int position) {
|
||||
holder.displayUser(getUser(position));
|
||||
}
|
||||
|
||||
holder.setUserColor(getUserColor(mContext, user.id));
|
||||
|
||||
holder.setTextSize(getTextSize());
|
||||
final int userTypeRes = getUserTypeIconRes(user.is_verified, user.is_protected);
|
||||
if (userTypeRes != 0) {
|
||||
holder.profile_type.setImageResource(userTypeRes);
|
||||
} else {
|
||||
holder.profile_type.setImageDrawable(null);
|
||||
}
|
||||
holder.name.setText(getUserNickname(mContext, user.id, user.name));
|
||||
holder.screen_name.setText("@" + user.screen_name);
|
||||
holder.description.setVisibility(TextUtils.isEmpty(user.description_unescaped) ? View.GONE : View.VISIBLE);
|
||||
holder.description.setText(user.description_unescaped);
|
||||
holder.location.setVisibility(TextUtils.isEmpty(user.location) ? View.GONE : View.VISIBLE);
|
||||
holder.location.setText(user.location);
|
||||
holder.url.setVisibility(TextUtils.isEmpty(user.url_expanded) ? View.GONE : View.VISIBLE);
|
||||
holder.url.setText(user.url_expanded);
|
||||
holder.statuses_count.setText(getLocalizedNumber(mLocale, user.statuses_count));
|
||||
holder.followers_count.setText(getLocalizedNumber(mLocale, user.followers_count));
|
||||
holder.friends_count.setText(getLocalizedNumber(mLocale, user.friends_count));
|
||||
holder.profile_image.setVisibility(isProfileImageDisplayed() ? View.VISIBLE : View.GONE);
|
||||
if (isProfileImageDisplayed()) {
|
||||
mProfileImageLoader.displayProfileImage(holder.profile_image, user.profile_image_url);
|
||||
}
|
||||
return view;
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return getUsersCount() + (isLoadMoreIndicatorVisible() ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
public void setData(final List<ParcelableUser> data) {
|
||||
setData(data, false);
|
||||
@Override
|
||||
public ParcelableUser getUser(int position) {
|
||||
if (position == getUsersCount()) return null;
|
||||
return mData.get(position);
|
||||
}
|
||||
|
||||
public void setData(final List<ParcelableUser> data, final boolean clear_old) {
|
||||
if (clear_old) {
|
||||
clear();
|
||||
}
|
||||
if (data == null) return;
|
||||
for (final ParcelableUser user : data) {
|
||||
if (clear_old || findItemPosition(user.id) < 0) {
|
||||
add(user);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public long getUserId(int position) {
|
||||
if (position == getUsersCount()) return -1;
|
||||
return mData.get(position).id;
|
||||
}
|
||||
|
||||
|
||||
private static int getItemResource(final boolean compactCards) {
|
||||
return compactCards ? R.layout.card_item_user_compact : R.layout.card_item_user;
|
||||
@Override
|
||||
public int getUsersCount() {
|
||||
if (mData == null) return 0;
|
||||
return mData.size();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,11 +20,14 @@
|
|||
package org.mariotaku.twidere.adapter.iface;
|
||||
|
||||
import org.mariotaku.twidere.model.ParcelableActivity;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.MediaLoadingHandler;
|
||||
import org.mariotaku.twidere.view.CardMediaContainer.PreviewStyle;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 14/11/18.
|
||||
*/
|
||||
public interface IActivitiesAdapter<Data> extends IContentCardAdapter {
|
||||
public interface IActivitiesAdapter<Data> extends IContentCardAdapter, IGapSupportedAdapter {
|
||||
|
||||
ParcelableActivity getActivity(int position);
|
||||
|
||||
|
@ -32,4 +35,10 @@ public interface IActivitiesAdapter<Data> extends IContentCardAdapter {
|
|||
|
||||
void setData(Data data);
|
||||
|
||||
@PreviewStyle
|
||||
int getMediaPreviewStyle();
|
||||
|
||||
MediaLoaderWrapper getMediaLoader();
|
||||
|
||||
MediaLoadingHandler getMediaLoadingHandler();
|
||||
}
|
||||
|
|
|
@ -20,40 +20,29 @@
|
|||
package org.mariotaku.twidere.adapter.iface;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.ImageLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.view.CardMediaContainer.PreviewStyle;
|
||||
import org.mariotaku.twidere.view.ShapedImageView.ShapeStyle;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/1/3.
|
||||
*/
|
||||
public interface IContentCardAdapter extends IGapSupportedAdapter, ContentCardClickListener {
|
||||
MediaLoaderWrapper getImageLoader();
|
||||
|
||||
public interface IContentCardAdapter extends ILoadMoreSupportAdapter {
|
||||
Context getContext();
|
||||
|
||||
ImageLoadingHandler getImageLoadingHandler();
|
||||
|
||||
int getItemCount();
|
||||
|
||||
@ShapeStyle
|
||||
int getProfileImageStyle();
|
||||
|
||||
@PreviewStyle
|
||||
int getMediaPreviewStyle();
|
||||
|
||||
AsyncTwitterWrapper getTwitterWrapper();
|
||||
|
||||
float getTextSize();
|
||||
|
||||
boolean isLoadMoreIndicatorVisible();
|
||||
@NonNull
|
||||
AsyncTwitterWrapper getTwitterWrapper();
|
||||
|
||||
boolean isLoadMoreSupported();
|
||||
boolean isProfileImageEnabled();
|
||||
|
||||
void setLoadMoreSupported(boolean supported);
|
||||
|
||||
void setLoadMoreIndicatorVisible(boolean enabled);
|
||||
MediaLoaderWrapper getMediaLoader();
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ import android.support.v7.widget.RecyclerView.ViewHolder;
|
|||
*/
|
||||
public interface IGapSupportedAdapter {
|
||||
|
||||
int ITEM_VIEW_TYPE_GAP = 1;
|
||||
|
||||
boolean isGapItem(int position);
|
||||
|
||||
void onGapClick(ViewHolder holder, int position);
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.iface;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/16.
|
||||
*/
|
||||
public interface ILoadMoreSupportAdapter {
|
||||
int ITEM_VIEW_TYPE_LOAD_INDICATOR = 0;
|
||||
|
||||
boolean isLoadMoreIndicatorVisible();
|
||||
|
||||
void setLoadMoreIndicatorVisible(boolean enabled);
|
||||
|
||||
boolean isLoadMoreSupported();
|
||||
|
||||
void setLoadMoreSupported(boolean supported);
|
||||
}
|
|
@ -1,33 +1,42 @@
|
|||
package org.mariotaku.twidere.adapter.iface;
|
||||
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.MediaLoadingHandler;
|
||||
import org.mariotaku.twidere.util.TwidereLinkify;
|
||||
import org.mariotaku.twidere.view.CardMediaContainer.PreviewStyle;
|
||||
import org.mariotaku.twidere.view.holder.StatusViewHolder.StatusClickListener;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 14/11/18.
|
||||
*/
|
||||
public interface IStatusesAdapter<Data> extends IContentCardAdapter, StatusClickListener {
|
||||
public interface IStatusesAdapter<Data> extends IContentCardAdapter, StatusClickListener,
|
||||
IGapSupportedAdapter, ContentCardClickListener {
|
||||
|
||||
int getLinkHighlightingStyle();
|
||||
|
||||
@PreviewStyle
|
||||
int getMediaPreviewStyle();
|
||||
|
||||
ParcelableStatus getStatus(int position);
|
||||
|
||||
int getStatusesCount();
|
||||
|
||||
long getStatusId(int position);
|
||||
|
||||
int getStatusesCount();
|
||||
|
||||
TwidereLinkify getTwidereLinkify();
|
||||
|
||||
boolean isMediaPreviewEnabled();
|
||||
boolean isCardActionsHidden();
|
||||
|
||||
int getLinkHighlightingStyle();
|
||||
boolean isMediaPreviewEnabled();
|
||||
|
||||
boolean isNameFirst();
|
||||
|
||||
boolean isSensitiveContentEnabled();
|
||||
|
||||
boolean isCardActionsHidden();
|
||||
|
||||
void setData(Data data);
|
||||
|
||||
boolean shouldShowAccountsColor();
|
||||
|
||||
MediaLoadingHandler getMediaLoadingHandler();
|
||||
}
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 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.iface;
|
||||
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
|
||||
public interface IStatusesListAdapter<Data> extends IBaseCardAdapter, IStatusesAdapter<Data> {
|
||||
|
||||
public int findPositionByStatusId(final long statusId);
|
||||
|
||||
public long getAccountId(final int position);
|
||||
|
||||
public ParcelableStatus getLastStatus();
|
||||
|
||||
public long getLastStatusId();
|
||||
|
||||
public long getStatusId(final int position);
|
||||
|
||||
public boolean isLastItemFiltered();
|
||||
|
||||
public void setCardHighlightOption(String option);
|
||||
|
||||
public void setDisplayImagePreview(boolean display);
|
||||
|
||||
public void setDisplaySensitiveContents(boolean display);
|
||||
|
||||
public void setFavoritesHightlightDisabled(boolean disable);
|
||||
|
||||
public void setFiltersEnabled(boolean enabled);
|
||||
|
||||
public void setGapDisallowed(boolean disallowed);
|
||||
|
||||
public void setHighlightKeyword(String... keywords);
|
||||
|
||||
public void setIgnoredFilterFields(final boolean user, final boolean textPlain, final boolean textHtml,
|
||||
final boolean source, final boolean retweetedById);
|
||||
|
||||
public void setImagePreviewScaleType(String scaleType);
|
||||
|
||||
public void setIndicateMyStatusDisabled(boolean disable);
|
||||
|
||||
public void setMentionsHightlightDisabled(boolean disable);
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.iface;
|
||||
|
||||
import org.mariotaku.twidere.model.ParcelableUser;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.MediaLoadingHandler;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/16.
|
||||
*/
|
||||
public interface IUsersAdapter<Data> extends IContentCardAdapter {
|
||||
|
||||
ParcelableUser getUser(int position);
|
||||
|
||||
long getUserId(int position);
|
||||
|
||||
int getUsersCount();
|
||||
|
||||
void setData(Data data);
|
||||
|
||||
boolean shouldShowAccountsColor();
|
||||
|
||||
MediaLoaderWrapper getMediaLoader();
|
||||
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* 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.fragment.support;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
|
||||
import android.support.v7.widget.FixedLinearLayoutManager;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.activity.iface.IControlBarActivity;
|
||||
import org.mariotaku.twidere.activity.iface.IControlBarActivity.ControlBarOffsetListener;
|
||||
import org.mariotaku.twidere.activity.support.BaseActionBarActivity;
|
||||
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration;
|
||||
import org.mariotaku.twidere.adapter.iface.IContentCardAdapter;
|
||||
import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface;
|
||||
import org.mariotaku.twidere.util.ColorUtils;
|
||||
import org.mariotaku.twidere.util.ContentListScrollListener;
|
||||
import org.mariotaku.twidere.util.ContentListScrollListener.ContentListSupport;
|
||||
import org.mariotaku.twidere.util.SimpleDrawerCallback;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/16.
|
||||
*/
|
||||
public abstract class AbsContentListFragment<A extends IContentCardAdapter> extends BaseSupportFragment implements OnRefreshListener,
|
||||
DrawerCallback, RefreshScrollTopInterface, ControlBarOffsetListener, ContentListSupport {
|
||||
|
||||
private Rect mSystemWindowsInsets = new Rect();
|
||||
private int mControlBarOffsetPixels;
|
||||
private LinearLayoutManager mLayoutManager;
|
||||
private View mProgressContainer;
|
||||
private SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
private RecyclerView mRecyclerView;
|
||||
private SimpleDrawerCallback mDrawerCallback;
|
||||
|
||||
private A mAdapter;
|
||||
private ContentListScrollListener mScrollListener;
|
||||
|
||||
public boolean canScroll(float dy) {
|
||||
return mDrawerCallback.canScroll(dy);
|
||||
}
|
||||
|
||||
public void cancelTouch() {
|
||||
mDrawerCallback.cancelTouch();
|
||||
}
|
||||
|
||||
public void fling(float velocity) {
|
||||
mDrawerCallback.fling(velocity);
|
||||
}
|
||||
|
||||
public boolean isScrollContent(float x, float y) {
|
||||
return mDrawerCallback.isScrollContent(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onControlBarOffsetChanged(IControlBarActivity activity, float offset) {
|
||||
mControlBarOffsetPixels = Math.round(activity.getControlBarHeight() * (1 - offset));
|
||||
updateRefreshProgressOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
triggerRefresh();
|
||||
}
|
||||
|
||||
public void scrollBy(float dy) {
|
||||
mDrawerCallback.scrollBy(dy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean scrollToStart() {
|
||||
mLayoutManager.scrollToPositionWithOffset(0, 0);
|
||||
mRecyclerView.stopScroll();
|
||||
setControlVisible(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setControlVisible(boolean visible) {
|
||||
final FragmentActivity activity = getActivity();
|
||||
if (activity instanceof BaseActionBarActivity) {
|
||||
((BaseActionBarActivity) activity).setControlBarVisibleAnimate(visible);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean shouldLayoutHeaderBottom() {
|
||||
return mDrawerCallback.shouldLayoutHeaderBottom();
|
||||
}
|
||||
|
||||
public void topChanged(int offset) {
|
||||
mDrawerCallback.topChanged(offset);
|
||||
}
|
||||
|
||||
public A getAdapter() {
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
public abstract boolean isRefreshing();
|
||||
|
||||
public LinearLayoutManager getLayoutManager() {
|
||||
return mLayoutManager;
|
||||
}
|
||||
|
||||
public void setRefreshing(boolean refreshing) {
|
||||
if (refreshing == mSwipeRefreshLayout.isRefreshing()) return;
|
||||
// if (!refreshing) updateRefreshProgressOffset();
|
||||
mSwipeRefreshLayout.setRefreshing(refreshing && !mAdapter.isLoadMoreIndicatorVisible());
|
||||
}
|
||||
|
||||
public void onLoadMoreContents() {
|
||||
setLoadMoreIndicatorVisible(true);
|
||||
setRefreshEnabled(false);
|
||||
}
|
||||
|
||||
public final RecyclerView getRecyclerView() {
|
||||
return mRecyclerView;
|
||||
}
|
||||
|
||||
public final ContentListScrollListener getScrollListener() {
|
||||
return mScrollListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
if (activity instanceof IControlBarActivity) {
|
||||
((IControlBarActivity) activity).registerControlBarOffsetListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_recycler_view, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
mDrawerCallback = new SimpleDrawerCallback(mRecyclerView);
|
||||
|
||||
final View view = getView();
|
||||
if (view == null) throw new AssertionError();
|
||||
final Context context = view.getContext();
|
||||
final boolean compact = Utils.isCompactCards(context);
|
||||
final int backgroundColor = ThemeUtils.getThemeBackgroundColor(context);
|
||||
final int colorRes = ColorUtils.getContrastYIQ(backgroundColor,
|
||||
R.color.bg_refresh_progress_color_light, R.color.bg_refresh_progress_color_dark);
|
||||
mSwipeRefreshLayout.setOnRefreshListener(this);
|
||||
mSwipeRefreshLayout.setColorSchemeColors(ThemeUtils.getUserAccentColor(context));
|
||||
mSwipeRefreshLayout.setProgressBackgroundColorSchemeResource(colorRes);
|
||||
mAdapter = onCreateAdapter(context, compact);
|
||||
mLayoutManager = new FixedLinearLayoutManager(context);
|
||||
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
|
||||
mRecyclerView.setLayoutManager(mLayoutManager);
|
||||
mRecyclerView.setHasFixedSize(true);
|
||||
if (compact) {
|
||||
mRecyclerView.addItemDecoration(new DividerItemDecoration(context, mLayoutManager.getOrientation()));
|
||||
}
|
||||
mRecyclerView.setAdapter((RecyclerView.Adapter) mAdapter);
|
||||
|
||||
mScrollListener = new ContentListScrollListener(this);
|
||||
mScrollListener.setTouchSlop(ViewConfiguration.get(context).getScaledTouchSlop());
|
||||
mRecyclerView.setOnScrollListener(mScrollListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBaseViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onBaseViewCreated(view, savedInstanceState);
|
||||
mProgressContainer = view.findViewById(R.id.progress_container);
|
||||
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_layout);
|
||||
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
final FragmentActivity activity = getActivity();
|
||||
if (activity instanceof IControlBarActivity) {
|
||||
((IControlBarActivity) activity).unregisterControlBarOffsetListener(this);
|
||||
}
|
||||
super.onDetach();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fitSystemWindows(Rect insets) {
|
||||
super.fitSystemWindows(insets);
|
||||
mRecyclerView.setPadding(insets.left, insets.top, insets.right, insets.bottom);
|
||||
mProgressContainer.setPadding(insets.left, insets.top, insets.right, insets.bottom);
|
||||
mSystemWindowsInsets.set(insets);
|
||||
updateRefreshProgressOffset();
|
||||
}
|
||||
|
||||
public void setLoadMoreIndicatorVisible(boolean visible) {
|
||||
mAdapter.setLoadMoreIndicatorVisible(visible);
|
||||
}
|
||||
|
||||
public void setRefreshEnabled(boolean enabled) {
|
||||
mSwipeRefreshLayout.setEnabled(enabled);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected abstract A onCreateAdapter(Context context, boolean compact);
|
||||
|
||||
protected final void setListShown(boolean shown) {
|
||||
mProgressContainer.setVisibility(shown ? View.GONE : View.VISIBLE);
|
||||
mSwipeRefreshLayout.setVisibility(shown ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
protected void updateRefreshProgressOffset() {
|
||||
if (mSystemWindowsInsets.top == 0 || mSwipeRefreshLayout == null || isRefreshing()) return;
|
||||
final float density = getResources().getDisplayMetrics().density;
|
||||
final int progressCircleDiameter = mSwipeRefreshLayout.getProgressCircleDiameter();
|
||||
final int swipeStart = (mSystemWindowsInsets.top - mControlBarOffsetPixels) - progressCircleDiameter;
|
||||
// 64: SwipeRefreshLayout.DEFAULT_CIRCLE_TARGET
|
||||
final int swipeDistance = Math.round(64 * density);
|
||||
mSwipeRefreshLayout.setProgressViewOffset(false, swipeStart, swipeStart + swipeDistance);
|
||||
}
|
||||
}
|
|
@ -1,19 +1,14 @@
|
|||
package org.mariotaku.twidere.fragment.support;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
|
||||
import android.support.v7.widget.FixedLinearLayoutManager;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.PopupMenu;
|
||||
import android.support.v7.widget.PopupMenu.OnMenuItemClickListener;
|
||||
|
@ -21,40 +16,26 @@ import android.support.v7.widget.RecyclerView;
|
|||
import android.support.v7.widget.RecyclerView.OnScrollListener;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.squareup.otto.Bus;
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.activity.iface.IControlBarActivity;
|
||||
import org.mariotaku.twidere.activity.iface.IControlBarActivity.ControlBarOffsetListener;
|
||||
import org.mariotaku.twidere.activity.support.BaseActionBarActivity;
|
||||
import org.mariotaku.twidere.adapter.AbsStatusesAdapter;
|
||||
import org.mariotaku.twidere.adapter.AbsStatusesAdapter.StatusAdapterListener;
|
||||
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface;
|
||||
import org.mariotaku.twidere.loader.iface.IExtendedLoader;
|
||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.ColorUtils;
|
||||
import org.mariotaku.twidere.util.ContentListScrollListener;
|
||||
import org.mariotaku.twidere.util.ContentListScrollListener.ContentListSupport;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.ShortcutCallback;
|
||||
import org.mariotaku.twidere.util.ReadStateManager;
|
||||
import org.mariotaku.twidere.util.RecyclerViewUtils;
|
||||
import org.mariotaku.twidere.util.SimpleDrawerCallback;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.util.message.StatusListChangedEvent;
|
||||
import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback;
|
||||
import org.mariotaku.twidere.view.holder.GapViewHolder;
|
||||
import org.mariotaku.twidere.view.holder.StatusViewHolder;
|
||||
|
||||
|
@ -66,27 +47,15 @@ import static org.mariotaku.twidere.util.Utils.setMenuForStatus;
|
|||
/**
|
||||
* Created by mariotaku on 14/11/5.
|
||||
*/
|
||||
public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment implements LoaderCallbacks<Data>,
|
||||
OnRefreshListener, DrawerCallback, RefreshScrollTopInterface, StatusAdapterListener,
|
||||
ControlBarOffsetListener, ContentListSupport, ShortcutCallback {
|
||||
public abstract class AbsStatusesFragment<Data> extends AbsContentListFragment<AbsStatusesAdapter<Data>>
|
||||
implements LoaderCallbacks<Data>, StatusAdapterListener, ShortcutCallback {
|
||||
|
||||
private final Object mStatusesBusCallback;
|
||||
private AbsStatusesAdapter<Data> mAdapter;
|
||||
private LinearLayoutManager mLayoutManager;
|
||||
private SharedPreferences mPreferences;
|
||||
private View mProgressContainer;
|
||||
private SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
private RecyclerView mRecyclerView;
|
||||
private SimpleDrawerCallback mDrawerCallback;
|
||||
private Rect mSystemWindowsInsets = new Rect();
|
||||
private int mControlBarOffsetPixels;
|
||||
private PopupMenu mPopupMenu;
|
||||
private ReadStateManager mReadStateManager;
|
||||
private KeyboardShortcutsHandler mKeyboardShortcutsHandler;
|
||||
private ParcelableStatus mSelectedStatus;
|
||||
|
||||
private int mPositionBackup;
|
||||
|
||||
private OnMenuItemClickListener mOnStatusMenuItemClickListener = new OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
|
@ -101,65 +70,23 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
getFragmentManager(), getTwitterWrapper(), status, item);
|
||||
}
|
||||
};
|
||||
private int mPositionBackup;
|
||||
|
||||
protected AbsStatusesFragment() {
|
||||
mStatusesBusCallback = createMessageBusCallback();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canScroll(float dy) {
|
||||
return mDrawerCallback.canScroll(dy);
|
||||
public SharedPreferences getSharedPreferences() {
|
||||
if (mPreferences != null) return mPreferences;
|
||||
return mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelTouch() {
|
||||
mDrawerCallback.cancelTouch();
|
||||
}
|
||||
public abstract int getStatuses(long[] accountIds, long[] maxIds, long[] sinceIds);
|
||||
|
||||
@Override
|
||||
public void fling(float velocity) {
|
||||
mDrawerCallback.fling(velocity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isScrollContent(float x, float y) {
|
||||
return mDrawerCallback.isScrollContent(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleKeyboardShortcutRepeat(int keyCode, int repeatCount, @NonNull KeyEvent event) {
|
||||
if (!KeyboardShortcutsHandler.isValidForHotkey(keyCode, event)) return false;
|
||||
String action = mKeyboardShortcutsHandler.getKeyAction("navigation", keyCode, event);
|
||||
final LinearLayoutManager layoutManager = mLayoutManager;
|
||||
final RecyclerView recyclerView = mRecyclerView;
|
||||
final View focusedChild = RecyclerViewUtils.findRecyclerViewChild(recyclerView, layoutManager.getFocusedChild());
|
||||
final int position;
|
||||
if (focusedChild != null) {
|
||||
position = recyclerView.getChildLayoutPosition(focusedChild);
|
||||
} else if (layoutManager.findFirstVisibleItemPosition() == 0) {
|
||||
position = -1;
|
||||
} else {
|
||||
final int itemCount = mAdapter.getItemCount();
|
||||
if (layoutManager.findLastVisibleItemPosition() == itemCount - 1) {
|
||||
position = itemCount;
|
||||
} else {
|
||||
position = mPositionBackup;
|
||||
}
|
||||
}
|
||||
mPositionBackup = position;
|
||||
if (action != null) {
|
||||
switch (action) {
|
||||
case "navigation.previous": {
|
||||
RecyclerViewUtils.focusNavigate(recyclerView, layoutManager, position, -1);
|
||||
return true;
|
||||
}
|
||||
case "navigation.next": {
|
||||
RecyclerViewUtils.focusNavigate(recyclerView, layoutManager, position, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
public final boolean scrollToStart() {
|
||||
saveReadPosition();
|
||||
return super.scrollToStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -170,7 +97,9 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
triggerRefresh();
|
||||
return true;
|
||||
}
|
||||
final View focusedChild = RecyclerViewUtils.findRecyclerViewChild(mRecyclerView, mLayoutManager.getFocusedChild());
|
||||
final RecyclerView mRecyclerView = getRecyclerView();
|
||||
final LinearLayoutManager layoutManager = getLayoutManager();
|
||||
final View focusedChild = RecyclerViewUtils.findRecyclerViewChild(mRecyclerView, layoutManager.getFocusedChild());
|
||||
final int position;
|
||||
if (focusedChild != null && focusedChild.getParent() == mRecyclerView) {
|
||||
position = mRecyclerView.getChildLayoutPosition(focusedChild);
|
||||
|
@ -178,7 +107,7 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
return false;
|
||||
}
|
||||
if (position == -1) return false;
|
||||
final ParcelableStatus status = mAdapter.getStatus(position);
|
||||
final ParcelableStatus status = getAdapter().getStatus(position);
|
||||
if (status == null) return false;
|
||||
if (action == null) {
|
||||
action = mKeyboardShortcutsHandler.getKeyAction("status", keyCode, event);
|
||||
|
@ -209,57 +138,39 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
}
|
||||
|
||||
@Override
|
||||
public void scrollBy(float dy) {
|
||||
mDrawerCallback.scrollBy(dy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldLayoutHeaderBottom() {
|
||||
return mDrawerCallback.shouldLayoutHeaderBottom();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void topChanged(int offset) {
|
||||
mDrawerCallback.topChanged(offset);
|
||||
}
|
||||
|
||||
public SharedPreferences getSharedPreferences() {
|
||||
if (mPreferences != null) return mPreferences;
|
||||
return mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
public abstract int getStatuses(long[] accountIds, long[] maxIds, long[] sinceIds);
|
||||
|
||||
public abstract boolean isRefreshing();
|
||||
|
||||
public AbsStatusesAdapter<Data> getAdapter() {
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
public void setControlVisible(boolean visible) {
|
||||
final FragmentActivity activity = getActivity();
|
||||
if (activity instanceof BaseActionBarActivity) {
|
||||
((BaseActionBarActivity) activity).setControlBarVisibleAnimate(visible);
|
||||
public boolean handleKeyboardShortcutRepeat(int keyCode, int repeatCount, @NonNull KeyEvent event) {
|
||||
if (!KeyboardShortcutsHandler.isValidForHotkey(keyCode, event)) return false;
|
||||
String action = mKeyboardShortcutsHandler.getKeyAction("navigation", keyCode, event);
|
||||
final LinearLayoutManager layoutManager = getLayoutManager();
|
||||
final RecyclerView recyclerView = getRecyclerView();
|
||||
final View focusedChild = RecyclerViewUtils.findRecyclerViewChild(recyclerView, layoutManager.getFocusedChild());
|
||||
final int position;
|
||||
if (focusedChild != null) {
|
||||
position = recyclerView.getChildLayoutPosition(focusedChild);
|
||||
} else if (layoutManager.findFirstVisibleItemPosition() == 0) {
|
||||
position = -1;
|
||||
} else {
|
||||
final int itemCount = getAdapter().getItemCount();
|
||||
if (layoutManager.findLastVisibleItemPosition() == itemCount - 1) {
|
||||
position = itemCount;
|
||||
} else {
|
||||
position = mPositionBackup;
|
||||
}
|
||||
}
|
||||
|
||||
public void setRefreshing(boolean refreshing) {
|
||||
if (refreshing == mSwipeRefreshLayout.isRefreshing()) return;
|
||||
// if (!refreshing) updateRefreshProgressOffset();
|
||||
mSwipeRefreshLayout.setRefreshing(refreshing && !mAdapter.isLoadMoreIndicatorVisible());
|
||||
mPositionBackup = position;
|
||||
if (action != null) {
|
||||
switch (action) {
|
||||
case "navigation.previous": {
|
||||
RecyclerViewUtils.focusNavigate(recyclerView, layoutManager, position, -1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
if (activity instanceof IControlBarActivity) {
|
||||
((IControlBarActivity) activity).registerControlBarOffsetListener(this);
|
||||
case "navigation.next": {
|
||||
RecyclerViewUtils.focusNavigate(recyclerView, layoutManager, position, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_recycler_view, container, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -269,30 +180,8 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
final FragmentActivity activity = getActivity();
|
||||
final TwidereApplication application = TwidereApplication.getInstance(activity);
|
||||
mKeyboardShortcutsHandler = application.getKeyboardShortcutsHandler();
|
||||
final View view = getView();
|
||||
if (view == null) throw new AssertionError();
|
||||
final Context context = view.getContext();
|
||||
final boolean compact = Utils.isCompactCards(context);
|
||||
mDrawerCallback = new SimpleDrawerCallback(mRecyclerView);
|
||||
mSwipeRefreshLayout.setOnRefreshListener(this);
|
||||
mSwipeRefreshLayout.setColorSchemeColors(ThemeUtils.getUserAccentColor(context));
|
||||
final int backgroundColor = ThemeUtils.getThemeBackgroundColor(context);
|
||||
final int colorRes = ColorUtils.getContrastYIQ(backgroundColor,
|
||||
R.color.bg_refresh_progress_color_light, R.color.bg_refresh_progress_color_dark);
|
||||
mSwipeRefreshLayout.setProgressBackgroundColorSchemeResource(colorRes);
|
||||
mAdapter = onCreateAdapter(context, compact);
|
||||
mLayoutManager = new FixedLinearLayoutManager(context);
|
||||
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
|
||||
mRecyclerView.setLayoutManager(mLayoutManager);
|
||||
mRecyclerView.setHasFixedSize(true);
|
||||
if (compact) {
|
||||
mRecyclerView.addItemDecoration(new DividerItemDecoration(context, mLayoutManager.getOrientation()));
|
||||
}
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
|
||||
final ContentListScrollListener scrollListener = new ContentListScrollListener(this);
|
||||
scrollListener.setTouchSlop(ViewConfiguration.get(context).getScaledTouchSlop());
|
||||
scrollListener.setOnScrollListener(new OnScrollListener() {
|
||||
getAdapter().setListener(this);
|
||||
getScrollListener().setOnScrollListener(new OnScrollListener() {
|
||||
@Override
|
||||
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
|
||||
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
|
@ -300,78 +189,13 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
}
|
||||
}
|
||||
});
|
||||
mRecyclerView.setOnScrollListener(scrollListener);
|
||||
mAdapter.setListener(this);
|
||||
|
||||
final Bundle loaderArgs = new Bundle(getArguments());
|
||||
loaderArgs.putBoolean(EXTRA_FROM_USER, true);
|
||||
getLoaderManager().initLoader(0, loaderArgs, this);
|
||||
setListShown(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMoreContents() {
|
||||
setLoadMoreIndicatorVisible(true);
|
||||
setRefreshEnabled(false);
|
||||
}
|
||||
|
||||
public void setLoadMoreIndicatorVisible(boolean visible) {
|
||||
mAdapter.setLoadMoreIndicatorVisible(visible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
|
||||
bus.register(mStatusesBusCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
|
||||
bus.unregister(mStatusesBusCallback);
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (mPopupMenu != null) {
|
||||
mPopupMenu.dismiss();
|
||||
}
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBaseViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onBaseViewCreated(view, savedInstanceState);
|
||||
mProgressContainer = view.findViewById(R.id.progress_container);
|
||||
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_layout);
|
||||
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
final FragmentActivity activity = getActivity();
|
||||
if (activity instanceof IControlBarActivity) {
|
||||
((IControlBarActivity) activity).unregisterControlBarOffsetListener(this);
|
||||
}
|
||||
super.onDetach();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fitSystemWindows(Rect insets) {
|
||||
super.fitSystemWindows(insets);
|
||||
mRecyclerView.setPadding(insets.left, insets.top, insets.right, insets.bottom);
|
||||
mProgressContainer.setPadding(insets.left, insets.top, insets.right, insets.bottom);
|
||||
mSystemWindowsInsets.set(insets);
|
||||
updateRefreshProgressOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onControlBarOffsetChanged(IControlBarActivity activity, float offset) {
|
||||
mControlBarOffsetPixels = Math.round(activity.getControlBarHeight() * (1 - offset));
|
||||
updateRefreshProgressOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Loader<Data> onCreateLoader(int id, Bundle args) {
|
||||
final boolean fromUser = args.getBoolean(EXTRA_FROM_USER);
|
||||
|
@ -381,19 +205,21 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
|
||||
@Override
|
||||
public final void onLoadFinished(Loader<Data> loader, Data data) {
|
||||
final AbsStatusesAdapter<Data> adapter = getAdapter();
|
||||
final SharedPreferences preferences = getSharedPreferences();
|
||||
final boolean rememberPosition = preferences.getBoolean(KEY_REMEMBER_POSITION, false);
|
||||
final boolean readFromBottom = preferences.getBoolean(KEY_READ_FROM_BOTTOM, false);
|
||||
final long lastReadId;
|
||||
final int lastVisiblePos, lastVisibleTop;
|
||||
final String tag = getCurrentReadPositionTag();
|
||||
final LinearLayoutManager mLayoutManager = getLayoutManager();
|
||||
if (readFromBottom) {
|
||||
lastVisiblePos = mLayoutManager.findLastVisibleItemPosition();
|
||||
} else {
|
||||
lastVisiblePos = mLayoutManager.findFirstVisibleItemPosition();
|
||||
}
|
||||
if (lastVisiblePos != RecyclerView.NO_POSITION) {
|
||||
lastReadId = mAdapter.getStatusId(lastVisiblePos);
|
||||
lastReadId = adapter.getStatusId(lastVisiblePos);
|
||||
final View positionView = mLayoutManager.findViewByPosition(lastVisiblePos);
|
||||
lastVisibleTop = positionView != null ? positionView.getTop() : 0;
|
||||
} else if (rememberPosition && tag != null) {
|
||||
|
@ -403,18 +229,18 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
lastReadId = -1;
|
||||
lastVisibleTop = 0;
|
||||
}
|
||||
mAdapter.setData(data);
|
||||
adapter.setData(data);
|
||||
if (!(loader instanceof IExtendedLoader) || ((IExtendedLoader) loader).isFromUser()) {
|
||||
mAdapter.setLoadMoreSupported(hasMoreData(data));
|
||||
adapter.setLoadMoreSupported(hasMoreData(data));
|
||||
setRefreshEnabled(true);
|
||||
int pos = -1;
|
||||
for (int i = 0, j = mAdapter.getItemCount(); i < j; i++) {
|
||||
if (lastReadId != -1 && lastReadId == mAdapter.getStatusId(i)) {
|
||||
for (int i = 0, j = adapter.getItemCount(); i < j; i++) {
|
||||
if (lastReadId != -1 && lastReadId == adapter.getStatusId(i)) {
|
||||
pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pos != -1 && mAdapter.isStatus(pos) && (readFromBottom || lastVisiblePos != 0)) {
|
||||
if (pos != -1 && adapter.isStatus(pos) && (readFromBottom || lastVisiblePos != 0)) {
|
||||
mLayoutManager.scrollToPositionWithOffset(pos, lastVisibleTop);
|
||||
}
|
||||
}
|
||||
|
@ -425,12 +251,6 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
onLoadingFinished();
|
||||
}
|
||||
|
||||
protected abstract void onLoadingFinished();
|
||||
|
||||
public void setRefreshEnabled(boolean enabled) {
|
||||
mSwipeRefreshLayout.setEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Data> loader) {
|
||||
if (loader instanceof IExtendedLoader) {
|
||||
|
@ -443,17 +263,37 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
|
||||
@Override
|
||||
public void onGapClick(GapViewHolder holder, int position) {
|
||||
final ParcelableStatus status = mAdapter.getStatus(position);
|
||||
final long sinceId = position + 1 < mAdapter.getStatusesCount() ? mAdapter.getStatus(position + 1).id : -1;
|
||||
final AbsStatusesAdapter<Data> adapter = getAdapter();
|
||||
final ParcelableStatus status = adapter.getStatus(position);
|
||||
final long sinceId = position + 1 < adapter.getStatusesCount() ? adapter.getStatus(position + 1).id : -1;
|
||||
final long[] accountIds = {status.account_id};
|
||||
final long[] maxIds = {status.id};
|
||||
final long[] sinceIds = {sinceId};
|
||||
getStatuses(accountIds, maxIds, sinceIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaClick(StatusViewHolder holder, ParcelableMedia media, int position) {
|
||||
final AbsStatusesAdapter<Data> adapter = getAdapter();
|
||||
final ParcelableStatus status = adapter.getStatus(position);
|
||||
if (status == null) return;
|
||||
Utils.openMedia(getActivity(), status, media);
|
||||
//spice
|
||||
SpiceProfilingUtil.log(getActivity(),
|
||||
status.id + ",Clicked," + status.account_id + "," + status.user_id + "," + status.text_plain.length()
|
||||
+ "," + media.media_url + "," + TypeMappingUtil.getMediaType(media.type)
|
||||
+ "," + adapter.isMediaPreviewEnabled() + "," + status.timestamp);
|
||||
SpiceProfilingUtil.profile(getActivity(), status.account_id,
|
||||
status.id + ",Clicked," + status.account_id + "," + status.user_id + "," + status.text_plain.length()
|
||||
+ "," + media.media_url + "," + TypeMappingUtil.getMediaType(media.type)
|
||||
+ "," + adapter.isMediaPreviewEnabled() + "," + status.timestamp);
|
||||
//end
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusActionClick(StatusViewHolder holder, int id, int position) {
|
||||
final ParcelableStatus status = mAdapter.getStatus(position);
|
||||
final AbsStatusesAdapter<Data> adapter = getAdapter();
|
||||
final ParcelableStatus status = adapter.getStatus(position);
|
||||
if (status == null) return;
|
||||
final FragmentActivity activity = getActivity();
|
||||
switch (id) {
|
||||
|
@ -483,7 +323,14 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
|
||||
@Override
|
||||
public void onStatusClick(StatusViewHolder holder, int position) {
|
||||
Utils.openStatus(getActivity(), mAdapter.getStatus(position), null);
|
||||
final AbsStatusesAdapter<Data> adapter = getAdapter();
|
||||
Utils.openStatus(getActivity(), adapter.getStatus(position), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStatusLongClick(StatusViewHolder holder, int position) {
|
||||
//TODO handle long click event
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -491,28 +338,38 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
if (mPopupMenu != null) {
|
||||
mPopupMenu.dismiss();
|
||||
}
|
||||
final PopupMenu popupMenu = new PopupMenu(mAdapter.getContext(), menuView,
|
||||
final AbsStatusesAdapter<Data> adapter = getAdapter();
|
||||
final PopupMenu popupMenu = new PopupMenu(adapter.getContext(), menuView,
|
||||
Gravity.NO_GRAVITY, R.attr.actionOverflowMenuStyle, 0);
|
||||
popupMenu.setOnMenuItemClickListener(mOnStatusMenuItemClickListener);
|
||||
popupMenu.inflate(R.menu.action_status);
|
||||
final ParcelableStatus status = mAdapter.getStatus(position);
|
||||
setMenuForStatus(mAdapter.getContext(), popupMenu.getMenu(), status);
|
||||
final ParcelableStatus status = adapter.getStatus(position);
|
||||
setMenuForStatus(adapter.getContext(), popupMenu.getMenu(), status);
|
||||
popupMenu.show();
|
||||
mPopupMenu = popupMenu;
|
||||
mSelectedStatus = status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
triggerRefresh();
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
|
||||
bus.register(mStatusesBusCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean scrollToStart() {
|
||||
saveReadPosition();
|
||||
mLayoutManager.scrollToPositionWithOffset(0, 0);
|
||||
setControlVisible(true);
|
||||
return true;
|
||||
public void onStop() {
|
||||
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
|
||||
bus.unregister(mStatusesBusCallback);
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (mPopupMenu != null) {
|
||||
mPopupMenu.dismiss();
|
||||
}
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
protected Object createMessageBusCallback() {
|
||||
|
@ -522,11 +379,13 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
protected abstract long[] getAccountIds();
|
||||
|
||||
protected Data getAdapterData() {
|
||||
return mAdapter.getData();
|
||||
final AbsStatusesAdapter<Data> adapter = getAdapter();
|
||||
return adapter.getData();
|
||||
}
|
||||
|
||||
protected void setAdapterData(Data data) {
|
||||
mAdapter.setData(data);
|
||||
final AbsStatusesAdapter<Data> adapter = getAdapter();
|
||||
adapter.setData(data);
|
||||
}
|
||||
|
||||
protected String getReadPositionTag() {
|
||||
|
@ -535,14 +394,16 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
|
||||
protected abstract boolean hasMoreData(Data data);
|
||||
|
||||
protected abstract AbsStatusesAdapter<Data> onCreateAdapter(Context context, boolean compact);
|
||||
protected abstract void onLoadingFinished();
|
||||
|
||||
protected void saveReadPosition() {
|
||||
final String readPositionTag = getReadPositionTagWithAccounts();
|
||||
if (readPositionTag == null) return;
|
||||
final int position = mLayoutManager.findFirstVisibleItemPosition();
|
||||
final LinearLayoutManager layoutManager = getLayoutManager();
|
||||
final int position = layoutManager.findFirstVisibleItemPosition();
|
||||
if (position == RecyclerView.NO_POSITION) return;
|
||||
final ParcelableStatus status = mAdapter.getStatus(position);
|
||||
final AbsStatusesAdapter<Data> adapter = getAdapter();
|
||||
final ParcelableStatus status = adapter.getStatus(position);
|
||||
if (status == null) return;
|
||||
mReadStateManager.setPosition(readPositionTag, status.id);
|
||||
mReadStateManager.setPosition(getCurrentReadPositionTag(), status.id, true);
|
||||
|
@ -558,38 +419,6 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
return Utils.getReadPositionTagWithAccounts(getReadPositionTag(), getAccountIds());
|
||||
}
|
||||
|
||||
private void setListShown(boolean shown) {
|
||||
mProgressContainer.setVisibility(shown ? View.GONE : View.VISIBLE);
|
||||
mSwipeRefreshLayout.setVisibility(shown ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaClick(StatusViewHolder holder, ParcelableMedia media, int position) {
|
||||
final ParcelableStatus status = mAdapter.getStatus(position);
|
||||
if (status == null) return;
|
||||
Utils.openMedia(getActivity(), status, media);
|
||||
//spice
|
||||
SpiceProfilingUtil.log(getActivity(),
|
||||
status.id + ",Clicked," + status.account_id + "," + status.user_id + "," + status.text_plain.length()
|
||||
+ "," + media.media_url + "," + TypeMappingUtil.getMediaType(media.type)
|
||||
+ "," + mAdapter.isMediaPreviewEnabled() + "," + status.timestamp);
|
||||
SpiceProfilingUtil.profile(getActivity(), status.account_id,
|
||||
status.id + ",Clicked," + status.account_id + "," + status.user_id + "," + status.text_plain.length()
|
||||
+ "," + media.media_url + "," + TypeMappingUtil.getMediaType(media.type)
|
||||
+ "," + mAdapter.isMediaPreviewEnabled() + "," + status.timestamp);
|
||||
//end
|
||||
}
|
||||
|
||||
private void updateRefreshProgressOffset() {
|
||||
if (mSystemWindowsInsets.top == 0 || mSwipeRefreshLayout == null || isRefreshing()) return;
|
||||
final float density = getResources().getDisplayMetrics().density;
|
||||
final int progressCircleDiameter = mSwipeRefreshLayout.getProgressCircleDiameter();
|
||||
final int swipeStart = (mSystemWindowsInsets.top - mControlBarOffsetPixels) - progressCircleDiameter;
|
||||
// 64: SwipeRefreshLayout.DEFAULT_CIRCLE_TARGET
|
||||
final int swipeDistance = Math.round(64 * density);
|
||||
mSwipeRefreshLayout.setProgressViewOffset(false, swipeStart, swipeStart + swipeDistance);
|
||||
}
|
||||
|
||||
protected final class StatusesBusCallback {
|
||||
|
||||
protected StatusesBusCallback() {
|
||||
|
@ -597,7 +426,8 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
|
||||
@Subscribe
|
||||
public void notifyStatusListChanged(StatusListChangedEvent event) {
|
||||
mAdapter.notifyDataSetChanged();
|
||||
final AbsStatusesAdapter<Data> adapter = getAdapter();
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* 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.fragment.support;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
|
||||
import org.mariotaku.twidere.adapter.AbsUsersAdapter;
|
||||
import org.mariotaku.twidere.loader.iface.IExtendedLoader;
|
||||
import org.mariotaku.twidere.model.ParcelableUser;
|
||||
|
||||
abstract class AbsUsersFragment<Data> extends AbsContentListFragment<AbsUsersAdapter<Data>> implements LoaderCallbacks<Data> {
|
||||
|
||||
public final Data getData() {
|
||||
return getAdapter().getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<Data> onCreateLoader(int id, Bundle args) {
|
||||
return newLoaderInstance(getActivity(), args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
final Bundle loaderArgs = new Bundle(getArguments());
|
||||
loaderArgs.putBoolean(EXTRA_FROM_USER, true);
|
||||
getLoaderManager().initLoader(0, loaderArgs, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onLoadFinished(Loader<Data> loader, Data data) {
|
||||
final AbsUsersAdapter<Data> adapter = getAdapter();
|
||||
final long lastReadId;
|
||||
final int lastVisiblePos, lastVisibleTop;
|
||||
final LinearLayoutManager layoutManager = getLayoutManager();
|
||||
lastVisiblePos = layoutManager.findFirstVisibleItemPosition();
|
||||
if (lastVisiblePos != RecyclerView.NO_POSITION) {
|
||||
lastReadId = adapter.getUserId(lastVisiblePos);
|
||||
final View positionView = layoutManager.findViewByPosition(lastVisiblePos);
|
||||
lastVisibleTop = positionView != null ? positionView.getTop() : 0;
|
||||
} else {
|
||||
lastReadId = -1;
|
||||
lastVisibleTop = 0;
|
||||
}
|
||||
adapter.setData(data);
|
||||
if (!(loader instanceof IExtendedLoader) || ((IExtendedLoader) loader).isFromUser()) {
|
||||
adapter.setLoadMoreSupported(hasMoreData(data));
|
||||
setRefreshEnabled(true);
|
||||
int pos = -1;
|
||||
for (int i = 0, j = adapter.getItemCount(); i < j; i++) {
|
||||
if (lastReadId != -1 && lastReadId == adapter.getUserId(i)) {
|
||||
pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pos != -1 && adapter.isUser(pos) && (lastVisiblePos != 0)) {
|
||||
layoutManager.scrollToPositionWithOffset(pos, lastVisibleTop);
|
||||
}
|
||||
}
|
||||
if (loader instanceof IExtendedLoader) {
|
||||
((IExtendedLoader) loader).setFromUser(false);
|
||||
}
|
||||
setListShown(true);
|
||||
onLoadingFinished(data);
|
||||
}
|
||||
|
||||
protected abstract boolean hasMoreData(Data data);
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Data> loader) {
|
||||
if (loader instanceof IExtendedLoader) {
|
||||
((IExtendedLoader) loader).setFromUser(false);
|
||||
}
|
||||
}
|
||||
|
||||
protected ParcelableUser getSelectedUser() {
|
||||
//TODO return selected
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract Loader<Data> newLoaderInstance(Context context, Bundle args);
|
||||
|
||||
protected abstract void onLoadingFinished(Data data);
|
||||
|
||||
}
|
|
@ -1,284 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 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.fragment.support;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MenuItem.OnMenuItemClickListener;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemLongClickListener;
|
||||
import android.widget.ListView;
|
||||
|
||||
import org.mariotaku.twidere.adapter.ParcelableUsersAdapter;
|
||||
import org.mariotaku.twidere.adapter.iface.IBaseCardAdapter.MenuButtonClickListener;
|
||||
import org.mariotaku.twidere.loader.support.DummyParcelableUsersLoader;
|
||||
import org.mariotaku.twidere.model.ParcelableUser;
|
||||
import org.mariotaku.twidere.util.MultiSelectManager;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.util.collection.NoDuplicatesArrayList;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mariotaku.twidere.util.Utils.clearListViewChoices;
|
||||
import static org.mariotaku.twidere.util.Utils.configBaseCardAdapter;
|
||||
import static org.mariotaku.twidere.util.Utils.getActivatedAccountIds;
|
||||
import static org.mariotaku.twidere.util.Utils.openUserProfile;
|
||||
|
||||
abstract class BaseUsersListFragment extends BasePullToRefreshListFragment implements
|
||||
LoaderCallbacks<List<ParcelableUser>>, OnItemLongClickListener, OnMenuItemClickListener,
|
||||
MultiSelectManager.Callback, MenuButtonClickListener {
|
||||
|
||||
private SharedPreferences mPreferences;
|
||||
private MultiSelectManager mMultiSelectManager;
|
||||
|
||||
private ParcelableUsersAdapter mAdapter;
|
||||
|
||||
private ListView mListView;
|
||||
private long mAccountId;
|
||||
|
||||
private final List<ParcelableUser> mData = Collections
|
||||
.synchronizedList(new NoDuplicatesArrayList<ParcelableUser>());
|
||||
private ParcelableUser mSelectedUser;
|
||||
|
||||
public long getAccountId() {
|
||||
return mAccountId;
|
||||
}
|
||||
|
||||
public final List<ParcelableUser> getData() {
|
||||
return mData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelableUsersAdapter getListAdapter() {
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
public SharedPreferences getSharedPreferences() {
|
||||
return mPreferences;
|
||||
}
|
||||
|
||||
public void loadMoreUsers() {
|
||||
if (isRefreshing()) return;
|
||||
final int count = mAdapter.getCount();
|
||||
if (count - 1 > 0) {
|
||||
final Bundle args = getArguments();
|
||||
if (args != null) {
|
||||
args.putLong(EXTRA_MAX_ID, mAdapter.getItem(count - 1).id);
|
||||
}
|
||||
if (!getLoaderManager().hasRunningLoaders()) {
|
||||
getLoaderManager().restartLoader(0, args, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(final Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
mAdapter = new ParcelableUsersAdapter(getActivity());
|
||||
mMultiSelectManager = getMultiSelectManager();
|
||||
mListView = getListView();
|
||||
mListView.setFastScrollEnabled(mPreferences.getBoolean(KEY_FAST_SCROLL_THUMB, false));
|
||||
final Bundle args = getArguments() != null ? getArguments() : new Bundle();
|
||||
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
|
||||
if (mAccountId != accountId) {
|
||||
mAdapter.clear();
|
||||
mData.clear();
|
||||
}
|
||||
mAccountId = accountId;
|
||||
if (!mPreferences.getBoolean(KEY_COMPACT_CARDS, false)) {
|
||||
mListView.setDivider(null);
|
||||
}
|
||||
mListView.setSelector(android.R.color.transparent);
|
||||
mListView.setOnItemLongClickListener(this);
|
||||
setListAdapter(mAdapter);
|
||||
getLoaderManager().initLoader(0, getArguments(), this);
|
||||
setListShown(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<List<ParcelableUser>> onCreateLoader(final int id, final Bundle args) {
|
||||
setProgressBarIndeterminateVisibility(true);
|
||||
final Loader<List<ParcelableUser>> loader = newLoaderInstance(getActivity(), args);
|
||||
return loader != null ? loader : new DummyParcelableUsersLoader(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemLongClick(final AdapterView<?> parent, final View view, final int position, final long id) {
|
||||
final ParcelableUsersAdapter adapter = getListAdapter();
|
||||
final int userPosition = adapter.findItemPosition(id);
|
||||
if (userPosition < 0) return false;
|
||||
final ParcelableUser user = adapter.getItem(userPosition);
|
||||
setItemSelected(user, position, !mMultiSelectManager.isSelected(user));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemsCleared() {
|
||||
clearListViewChoices(mListView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemSelected(final Object item) {
|
||||
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemUnselected(final Object item) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListItemClick(final ListView l, final View v, final int position, final long id) {
|
||||
final ParcelableUsersAdapter adapter = getListAdapter();
|
||||
final int userPosition = adapter.findItemPosition(id);
|
||||
if (userPosition < 0) return;
|
||||
final ParcelableUser user = adapter.getItem(userPosition);
|
||||
if (mMultiSelectManager.isActive()) {
|
||||
setItemSelected(user, position, !mMultiSelectManager.isSelected(user));
|
||||
return;
|
||||
}
|
||||
openUserProfile(getActivity(), user, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(final Loader<List<ParcelableUser>> loader) {
|
||||
setProgressBarIndeterminateVisibility(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(final Loader<List<ParcelableUser>> loader, final List<ParcelableUser> data) {
|
||||
setProgressBarIndeterminateVisibility(false);
|
||||
mAdapter.setData(data);
|
||||
mAdapter.setShowAccountColor(shouldShowAccountColor());
|
||||
setRefreshing(false);
|
||||
setListShown(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMenuButtonClick(final View button, final int position, final long id) {
|
||||
final ParcelableUser user = mAdapter.getItem(position - mListView.getHeaderViewsCount());
|
||||
if (user == null) return;
|
||||
showMenu(button, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(final MenuItem item) {
|
||||
if (mSelectedUser == null) return false;
|
||||
switch (item.getItemId()) {
|
||||
default: {
|
||||
if (item.getIntent() != null) {
|
||||
try {
|
||||
startActivity(item.getIntent());
|
||||
} catch (final ActivityNotFoundException e) {
|
||||
Log.w(LOGTAG, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReachedBottom() {
|
||||
loadMoreUsers();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
if (isRefreshing()) return;
|
||||
getLoaderManager().restartLoader(0, getArguments(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
configBaseCardAdapter(getActivity(), mAdapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
mMultiSelectManager.registerCallback(this);
|
||||
final int choiceMode = mListView.getChoiceMode();
|
||||
if (mMultiSelectManager.isActive()) {
|
||||
if (choiceMode != ListView.CHOICE_MODE_MULTIPLE) {
|
||||
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
|
||||
}
|
||||
} else {
|
||||
if (choiceMode != ListView.CHOICE_MODE_NONE) {
|
||||
Utils.clearListViewChoices(mListView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
mMultiSelectManager.unregisterCallback(this);
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
|
||||
protected ParcelableUser getSelectedUser() {
|
||||
return mSelectedUser;
|
||||
}
|
||||
|
||||
protected int getUserMenuResource() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected abstract Loader<List<ParcelableUser>> newLoaderInstance(Context context, Bundle args);
|
||||
|
||||
protected final void removeUsers(final long... userIds) {
|
||||
if (userIds == null || userIds.length == 0) return;
|
||||
for (final long userId : userIds) {
|
||||
mData.remove(mAdapter.findItemPosition(userId));
|
||||
}
|
||||
mAdapter.setData(mData, true);
|
||||
}
|
||||
|
||||
protected void setItemSelected(final ParcelableUser user, final int position, final boolean selected) {
|
||||
if (selected) {
|
||||
mMultiSelectManager.selectItem(user);
|
||||
} else {
|
||||
mMultiSelectManager.unselectItem(user);
|
||||
}
|
||||
mListView.setItemChecked(position, selected);
|
||||
}
|
||||
|
||||
protected boolean shouldShowAccountColor() {
|
||||
return getActivatedAccountIds(getActivity()).length > 1;
|
||||
}
|
||||
|
||||
private void showMenu(final View view, final ParcelableUser user) {
|
||||
mSelectedUser = user;
|
||||
//TODO show menu
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ import android.net.Uri;
|
|||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.content.Loader;
|
||||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
@ -172,6 +173,7 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment<Cursor>
|
|||
return cursor != null && cursor.getCount() != 0;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected CursorStatusesAdapter onCreateAdapter(final Context context, final boolean compact) {
|
||||
return new CursorStatusesAdapter(context, compact);
|
||||
|
|
|
@ -28,7 +28,7 @@ import org.mariotaku.twidere.model.ParcelableUser;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class CursorSupportUsersListFragment extends BaseUsersListFragment {
|
||||
public abstract class CursorSupportUsersListFragment extends ParcelableUsersFragment {
|
||||
|
||||
private long mNextCursor, mPrevCursor;
|
||||
|
||||
|
@ -58,15 +58,13 @@ public abstract class CursorSupportUsersListFragment extends BaseUsersListFragme
|
|||
mPrevCursor = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(final Loader<List<ParcelableUser>> loader, final List<ParcelableUser> data) {
|
||||
super.onLoadFinished(loader, data);
|
||||
final BaseCursorSupportUsersLoader cursorLoader = (BaseCursorSupportUsersLoader) loader;
|
||||
mNextCursor = cursorLoader.getNextCursor();
|
||||
mPrevCursor = cursorLoader.getPrevCursor();
|
||||
// TODO
|
||||
// setEnabled(mNextCursor > 0 ? "from_end" : "disabled");
|
||||
}
|
||||
// @Override
|
||||
// public void onLoadFinished(final Loader<List<ParcelableUser>> loader, final List<ParcelableUser> data) {
|
||||
// super.onLoadFinished(loader, data);
|
||||
// final BaseCursorSupportUsersLoader cursorLoader = (BaseCursorSupportUsersLoader) loader;
|
||||
// mNextCursor = cursorLoader.getNextCursor();
|
||||
// mPrevCursor = cursorLoader.getPrevCursor();
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(final Bundle outState) {
|
||||
|
|
|
@ -21,12 +21,9 @@ package org.mariotaku.twidere.fragment.support;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import org.mariotaku.twidere.loader.support.IDsUsersLoader;
|
||||
import org.mariotaku.twidere.loader.support.IncomingFriendshipsLoader;
|
||||
import org.mariotaku.twidere.model.ParcelableUser;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
|
||||
public class IncomingFriendshipsFragment extends CursorSupportUsersListFragment {
|
||||
|
||||
|
@ -37,25 +34,4 @@ public class IncomingFriendshipsFragment extends CursorSupportUsersListFragment
|
|||
return new IncomingFriendshipsLoader(context, accountId, getNextCursor(), getData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENU_ACCEPT: {
|
||||
final AsyncTwitterWrapper twitter = getTwitterWrapper();
|
||||
final ParcelableUser user = getSelectedUser();
|
||||
if (twitter == null || user == null) return false;
|
||||
twitter.acceptFriendshipAsync(user.account_id, user.id);
|
||||
break;
|
||||
}
|
||||
case MENU_DENY: {
|
||||
final AsyncTwitterWrapper twitter = getTwitterWrapper();
|
||||
final ParcelableUser user = getSelectedUser();
|
||||
if (twitter == null || user == null) return false;
|
||||
twitter.denyFriendshipAsync(user.account_id, user.id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onMenuItemClick(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.mariotaku.twidere.fragment.support;
|
|||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.mariotaku.twidere.adapter.CursorStatusesAdapter;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Mentions;
|
||||
|
@ -36,6 +37,7 @@ public class MentionsTimelineFragment extends CursorStatusesFragment {
|
|||
return Mentions.CONTENT_URI;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected CursorStatusesAdapter onCreateAdapter(Context context, boolean compact) {
|
||||
final CursorStatusesAdapter adapter = super.onCreateAdapter(context, compact);
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.mariotaku.twidere.fragment.support;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
|
||||
import com.squareup.otto.Bus;
|
||||
|
@ -107,6 +108,7 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment<Lis
|
|||
return new ParcelableStatusesBusCallback();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected ParcelableStatusesAdapter onCreateAdapter(final Context context, final boolean compact) {
|
||||
return new ParcelableStatusesAdapter(context, compact);
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 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.fragment.support;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
|
||||
import org.mariotaku.twidere.adapter.ParcelableUsersAdapter;
|
||||
import org.mariotaku.twidere.model.ParcelableUser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ParcelableUsersFragment extends AbsUsersFragment<List<ParcelableUser>> {
|
||||
|
||||
@Override
|
||||
public boolean isRefreshing() {
|
||||
final LoaderManager lm = getLoaderManager();
|
||||
return lm.hasRunningLoaders();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected final ParcelableUsersAdapter onCreateAdapter(Context context, boolean compact) {
|
||||
return new ParcelableUsersAdapter(context, compact);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean triggerRefresh() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected long getAccountId() {
|
||||
final Bundle args = getArguments();
|
||||
return args != null ? args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasMoreData(List<ParcelableUser> data) {
|
||||
return data == null || data.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLoadingFinished(List<ParcelableUser> data) {
|
||||
setRefreshEnabled(true);
|
||||
setRefreshing(false);
|
||||
setLoadMoreIndicatorVisible(false);
|
||||
}
|
||||
|
||||
protected void removeUsers(long... ids) {
|
||||
//TODO remove from adapter
|
||||
}
|
||||
|
||||
}
|
|
@ -21,17 +21,14 @@ package org.mariotaku.twidere.fragment.support;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.widget.AbsListView;
|
||||
import android.widget.AbsListView.OnScrollListener;
|
||||
|
||||
import org.mariotaku.twidere.loader.support.UserSearchLoader;
|
||||
import org.mariotaku.twidere.model.ParcelableUser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SearchUsersFragment extends BaseUsersListFragment {
|
||||
public class SearchUsersFragment extends ParcelableUsersFragment {
|
||||
|
||||
private int mPage = 1;
|
||||
|
||||
|
@ -58,11 +55,10 @@ public class SearchUsersFragment extends BaseUsersListFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(final Loader<List<ParcelableUser>> loader, final List<ParcelableUser> data) {
|
||||
public void onLoadingFinished(final List<ParcelableUser> data) {
|
||||
if (data != null) {
|
||||
mPage++;
|
||||
}
|
||||
super.onLoadFinished(loader, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -71,15 +67,4 @@ public class SearchUsersFragment extends BaseUsersListFragment {
|
|||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(final AbsListView view, final int scrollState) {
|
||||
super.onScrollStateChanged(view, scrollState);
|
||||
if (scrollState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
|
||||
final Fragment parent = getParentFragment();
|
||||
if (parent instanceof SearchFragment) {
|
||||
((SearchFragment) parent).hideIndicator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ import org.mariotaku.twidere.util.AsyncTaskUtils;
|
|||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.ClipboardUtils;
|
||||
import org.mariotaku.twidere.util.CompareUtils;
|
||||
import org.mariotaku.twidere.util.ImageLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoadingHandler;
|
||||
import org.mariotaku.twidere.util.LinkCreator;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.MenuUtils;
|
||||
|
@ -366,6 +366,11 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
openStatus(getActivity(), mStatusAdapter.getStatus(position), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStatusLongClick(StatusViewHolder holder, int position) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusMenuClick(StatusViewHolder holder, View menuView, int position) {
|
||||
//TODO show status menu
|
||||
|
@ -606,7 +611,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
final StatusFragment fragment = adapter.getFragment();
|
||||
final Context context = adapter.getContext();
|
||||
final Resources resources = context.getResources();
|
||||
final MediaLoaderWrapper loader = adapter.getImageLoader();
|
||||
final MediaLoaderWrapper loader = adapter.getMediaLoader();
|
||||
final boolean nameFirst = adapter.isNameFirst();
|
||||
|
||||
linkClickHandler.setStatus(status);
|
||||
|
@ -730,7 +735,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
mediaPreview.setVisibility(View.VISIBLE);
|
||||
mediaPreviewLoad.setVisibility(View.GONE);
|
||||
mediaPreview.displayMedia(status.media, loader, status.account_id,
|
||||
adapter.getFragment(), adapter.getImageLoadingHandler());
|
||||
adapter.getFragment(), adapter.getMediaLoadingHandler());
|
||||
} else {
|
||||
mediaPreviewContainer.setVisibility(View.VISIBLE);
|
||||
mediaPreview.setVisibility(View.GONE);
|
||||
|
@ -1021,7 +1026,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
private final StatusFragment mFragment;
|
||||
private final LayoutInflater mInflater;
|
||||
private final MediaLoaderWrapper mImageLoader;
|
||||
private final ImageLoadingHandler mImageLoadingHandler;
|
||||
private final MediaLoadingHandler mMediaLoadingHandler;
|
||||
private final TwidereLinkify mTwidereLinkify;
|
||||
|
||||
private final boolean mNameFirst;
|
||||
|
@ -1056,7 +1061,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
mContext = context;
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mImageLoader = TwidereApplication.getInstance(context).getMediaLoaderWrapper();
|
||||
mImageLoadingHandler = new ImageLoadingHandler(R.id.media_preview_progress);
|
||||
mMediaLoadingHandler = new MediaLoadingHandler(R.id.media_preview_progress);
|
||||
mCardBackgroundColor = ThemeUtils.getCardBackgroundColor(context);
|
||||
mNameFirst = preferences.getBoolean(KEY_NAME_FIRST, true);
|
||||
mTextSize = preferences.getInt(KEY_TEXT_SIZE, res.getInteger(R.integer.default_text_size));
|
||||
|
@ -1096,7 +1101,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
return mFragment;
|
||||
}
|
||||
|
||||
public MediaLoaderWrapper getImageLoader() {
|
||||
public MediaLoaderWrapper getMediaLoader() {
|
||||
return mImageLoader;
|
||||
}
|
||||
|
||||
|
@ -1105,8 +1110,8 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
}
|
||||
|
||||
@Override
|
||||
public ImageLoadingHandler getImageLoadingHandler() {
|
||||
return mImageLoadingHandler;
|
||||
public MediaLoadingHandler getMediaLoadingHandler() {
|
||||
return mMediaLoadingHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1119,6 +1124,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
return mMediaPreviewStyle;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AsyncTwitterWrapper getTwitterWrapper() {
|
||||
return mFragment.getTwitterWrapper();
|
||||
|
@ -1266,6 +1272,11 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStatusLongClick(StatusViewHolder holder, int position) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaClick(StatusViewHolder holder, ParcelableMedia media, int position) {
|
||||
if (mStatusAdapterListener != null) {
|
||||
|
|
|
@ -25,13 +25,9 @@ import android.content.Intent;
|
|||
import android.content.IntentFilter;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MenuItem.OnMenuItemClickListener;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.loader.support.CursorSupportUsersLoader;
|
||||
import org.mariotaku.twidere.loader.support.UserListMembersLoader;
|
||||
import org.mariotaku.twidere.model.ParcelableUser;
|
||||
import org.mariotaku.twidere.model.ParcelableUserList;
|
||||
import org.mariotaku.twidere.util.AsyncTaskUtils;
|
||||
|
||||
|
@ -41,7 +37,7 @@ import twitter4j.UserList;
|
|||
|
||||
import static org.mariotaku.twidere.util.Utils.getTwitterInstance;
|
||||
|
||||
public class UserListMembersFragment extends CursorSupportUsersListFragment implements OnMenuItemClickListener {
|
||||
public class UserListMembersFragment extends CursorSupportUsersListFragment {
|
||||
|
||||
private ParcelableUserList mUserList;
|
||||
|
||||
|
@ -91,22 +87,6 @@ public class UserListMembersFragment extends CursorSupportUsersListFragment impl
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(final MenuItem item) {
|
||||
final ParcelableUser user = getSelectedUser();
|
||||
if (user == null || mUserList == null) return false;
|
||||
switch (item.getItemId()) {
|
||||
case MENU_DELETE_FROM_LIST: {
|
||||
DeleteUserListMembersDialogFragment.show(getFragmentManager(), mUserList, user);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return super.onMenuItemClick(item);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(final Bundle outState) {
|
||||
outState.putParcelable(EXTRA_USER_LIST, mUserList);
|
||||
|
@ -126,11 +106,6 @@ public class UserListMembersFragment extends CursorSupportUsersListFragment impl
|
|||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getUserMenuResource() {
|
||||
return R.menu.action_user_list_member;
|
||||
}
|
||||
|
||||
private class GetUserListTask extends AsyncTask<Object, Object, ParcelableUserList> {
|
||||
|
||||
private final long accountId, userId;
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.mariotaku.twidere.app.TwidereApplication;
|
|||
import org.mariotaku.twidere.loader.support.MediaTimelineLoader;
|
||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.util.ImageLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.SimpleDrawerCallback;
|
||||
import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback;
|
||||
|
@ -162,13 +162,13 @@ public class UserMediaTimelineFragment extends BaseSupportFragment
|
|||
|
||||
private final LayoutInflater mInflater;
|
||||
private final MediaLoaderWrapper mImageLoader;
|
||||
private final ImageLoadingHandler mLoadingHandler;
|
||||
private final MediaLoadingHandler mLoadingHandler;
|
||||
private List<ParcelableStatus> mData;
|
||||
|
||||
MediaTimelineAdapter(Context context) {
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mImageLoader = TwidereApplication.getInstance(context).getMediaLoaderWrapper();
|
||||
mLoadingHandler = new ImageLoadingHandler(R.id.media_image_progress);
|
||||
mLoadingHandler = new MediaLoadingHandler(R.id.media_image_progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -208,7 +208,7 @@ public class UserMediaTimelineFragment extends BaseSupportFragment
|
|||
mediaTextView = (TextView) itemView.findViewById(R.id.media_text);
|
||||
}
|
||||
|
||||
public void setMedia(MediaLoaderWrapper loader, ImageLoadingHandler loadingHandler, ParcelableStatus status) {
|
||||
public void setMedia(MediaLoaderWrapper loader, MediaLoadingHandler loadingHandler, ParcelableStatus status) {
|
||||
final ParcelableMedia[] media = status.media;
|
||||
if (media == null || media.length < 1) return;
|
||||
final ParcelableMedia firstMedia = media[0];
|
||||
|
|
|
@ -28,7 +28,7 @@ import org.mariotaku.twidere.model.ParcelableUser;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
public class UsersListFragment extends BaseUsersListFragment {
|
||||
public class UsersListFragment extends ParcelableUsersFragment {
|
||||
|
||||
@Override
|
||||
public Loader<List<ParcelableUser>> newLoaderInstance(final Context context, final Bundle args) {
|
||||
|
|
|
@ -2383,7 +2383,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
+ status.user_id + "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count);
|
||||
} else {
|
||||
for (final ParcelableMedia spiceMedia : status.media) {
|
||||
if (TypeMappingUtil.getMediaType(spiceMedia.type).equals("image")) {
|
||||
if (spiceMedia.type == ParcelableMedia.TYPE_IMAGE) {
|
||||
SpiceProfilingUtil.log(getContext(), status.id + ",RetweetM," + account_id + ","
|
||||
+ status.user_id + "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + spiceMedia.media_url + "," + TypeMappingUtil.getMediaType(spiceMedia.type) + "," + spiceMedia.width + "x" + spiceMedia.height);
|
||||
|
|
|
@ -94,12 +94,12 @@ public class MediaLoaderWrapper implements Constants {
|
|||
mImageLoader.displayImage(uri, view, mImageDisplayOptions);
|
||||
}
|
||||
|
||||
public void displayPreviewImage(final ImageView view, final String url, final ImageLoadingHandler loadingHandler) {
|
||||
public void displayPreviewImage(final ImageView view, final String url, final MediaLoadingHandler loadingHandler) {
|
||||
mImageLoader.displayImage(url, view, mImageDisplayOptions, loadingHandler, loadingHandler);
|
||||
}
|
||||
|
||||
public void displayPreviewImageWithCredentials(final ImageView view, final String url, final long accountId,
|
||||
final ImageLoadingHandler loadingHandler) {
|
||||
final MediaLoadingHandler loadingHandler) {
|
||||
final DisplayImageOptions.Builder b = new DisplayImageOptions.Builder();
|
||||
b.cloneFrom(mImageDisplayOptions);
|
||||
b.extraForDownloader(new AccountExtra(accountId));
|
||||
|
|
|
@ -39,16 +39,16 @@ import org.mariotaku.twidere.view.ForegroundImageView;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ImageLoadingHandler implements ImageLoadingListener, ImageLoadingProgressListener {
|
||||
public class MediaLoadingHandler implements ImageLoadingListener, ImageLoadingProgressListener {
|
||||
|
||||
private final Map<View, String> mLoadingUris = new HashMap<>();
|
||||
private final int[] mProgressBarIds;
|
||||
|
||||
public ImageLoadingHandler() {
|
||||
public MediaLoadingHandler() {
|
||||
this(R.id.media_preview_progress);
|
||||
}
|
||||
|
||||
public ImageLoadingHandler(final int... progressBarIds) {
|
||||
public MediaLoadingHandler(final int... progressBarIds) {
|
||||
mProgressBarIds = progressBarIds;
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ import android.widget.TextView;
|
|||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.util.ImageLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.Utils.OnMediaClickListener;
|
||||
|
||||
|
@ -92,7 +92,7 @@ public class CardMediaContainer extends ViewGroup implements Constants {
|
|||
@NonNull final MediaLoaderWrapper loader,
|
||||
final long accountId,
|
||||
final OnMediaClickListener mediaClickListener,
|
||||
final ImageLoadingHandler loadingHandler) {
|
||||
final MediaLoadingHandler loadingHandler) {
|
||||
if (mediaArray == null || mMediaPreviewStyle == VALUE_MEDIA_PREVIEW_STYLE_CODE_NONE) {
|
||||
for (int i = 0, j = getChildCount(); i < j; i++) {
|
||||
final View child = getChildAt(i);
|
||||
|
|
|
@ -156,7 +156,7 @@ public class ActivityTitleSummaryViewHolder extends ViewHolder {
|
|||
}
|
||||
|
||||
private void displayUserProfileImages(final ParcelableUser[] statuses) {
|
||||
final MediaLoaderWrapper imageLoader = adapter.getImageLoader();
|
||||
final MediaLoaderWrapper imageLoader = adapter.getMediaLoader();
|
||||
if (statuses == null) {
|
||||
for (final ImageView view : profileImageViews) {
|
||||
imageLoader.cancelDisplayTask(view);
|
||||
|
|
|
@ -67,7 +67,7 @@ public class MessageEntryViewHolder extends ViewHolder implements OnClickListene
|
|||
|
||||
public void displayMessage(Cursor cursor, boolean isUnread) {
|
||||
final Context context = adapter.getContext();
|
||||
final MediaLoaderWrapper loader = adapter.getImageLoader();
|
||||
final MediaLoaderWrapper loader = adapter.getMediaLoader();
|
||||
|
||||
final long accountId = cursor.getLong(ConversationEntries.IDX_ACCOUNT_ID);
|
||||
final long conversationId = cursor.getLong(ConversationEntries.IDX_CONVERSATION_ID);
|
||||
|
|
|
@ -5,13 +5,13 @@ import android.database.Cursor;
|
|||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.CardView;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
import android.text.Html;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.View.OnLongClickListener;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
@ -25,7 +25,7 @@ import org.mariotaku.twidere.model.ParcelableMedia;
|
|||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus.CursorIndices;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.ImageLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoadingHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
|
||||
import org.mariotaku.twidere.util.SimpleValueSerializer;
|
||||
|
@ -53,8 +53,8 @@ import static org.mariotaku.twidere.util.Utils.getUserTypeIconRes;
|
|||
* <p/>
|
||||
* Created by mariotaku on 14/11/19.
|
||||
*/
|
||||
public class StatusViewHolder extends RecyclerView.ViewHolder implements Constants, OnClickListener,
|
||||
OnMediaClickListener {
|
||||
public class StatusViewHolder extends ViewHolder implements Constants, OnClickListener,
|
||||
OnMediaClickListener, OnLongClickListener {
|
||||
|
||||
@NonNull
|
||||
private final IStatusesAdapter<?> adapter;
|
||||
|
@ -135,7 +135,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
|
||||
public void displayStatus(@NonNull final ParcelableStatus status, @Nullable final TranslationResult translation,
|
||||
final boolean displayInReplyTo, final boolean shouldDisplayExtraType) {
|
||||
final MediaLoaderWrapper loader = adapter.getImageLoader();
|
||||
final MediaLoaderWrapper loader = adapter.getMediaLoader();
|
||||
final AsyncTwitterWrapper twitter = adapter.getTwitterWrapper();
|
||||
final TwidereLinkify linkify = adapter.getTwidereLinkify();
|
||||
final Context context = adapter.getContext();
|
||||
|
@ -255,7 +255,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
if (hasMedia && (adapter.isSensitiveContentEnabled() || !status.is_possibly_sensitive)) {
|
||||
mediaPreview.setVisibility(hasMedia ? View.VISIBLE : View.GONE);
|
||||
mediaPreview.displayMedia(status.media, loader, status.account_id, this,
|
||||
adapter.getImageLoadingHandler());
|
||||
adapter.getMediaLoadingHandler());
|
||||
} else {
|
||||
mediaPreview.setVisibility(View.GONE);
|
||||
}
|
||||
|
@ -272,8 +272,9 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
textView.setMovementMethod(null);
|
||||
}
|
||||
|
||||
final Locale locale = Locale.getDefault();
|
||||
if (reply_count > 0) {
|
||||
replyCountView.setText(Utils.getLocalizedNumber(Locale.getDefault(), reply_count));
|
||||
replyCountView.setText(Utils.getLocalizedNumber(locale, reply_count));
|
||||
} else {
|
||||
replyCountView.setText(null);
|
||||
}
|
||||
|
@ -288,7 +289,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
retweet_count = status.retweet_count + (creatingRetweet ? 1 : 0);
|
||||
}
|
||||
if (retweet_count > 0) {
|
||||
retweetCountView.setText(Utils.getLocalizedNumber(Locale.getDefault(), retweet_count));
|
||||
retweetCountView.setText(Utils.getLocalizedNumber(locale, retweet_count));
|
||||
} else {
|
||||
retweetCountView.setText(null);
|
||||
}
|
||||
|
@ -301,7 +302,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
favorite_count = status.favorite_count + (creatingFavorite ? 1 : 0);
|
||||
}
|
||||
if (favorite_count > 0) {
|
||||
favoriteCountView.setText(Utils.getLocalizedNumber(Locale.getDefault(), favorite_count));
|
||||
favoriteCountView.setText(Utils.getLocalizedNumber(locale, favorite_count));
|
||||
} else {
|
||||
favoriteCountView.setText(null);
|
||||
}
|
||||
|
@ -315,7 +316,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
|
||||
public void displayStatus(@NonNull Cursor cursor, @NonNull CursorIndices indices,
|
||||
final boolean displayInReplyTo) {
|
||||
final MediaLoaderWrapper loader = adapter.getImageLoader();
|
||||
final MediaLoaderWrapper loader = adapter.getMediaLoader();
|
||||
final AsyncTwitterWrapper twitter = adapter.getTwitterWrapper();
|
||||
final TwidereLinkify linkify = adapter.getTwidereLinkify();
|
||||
final Context context = adapter.getContext();
|
||||
|
@ -459,7 +460,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
final boolean hasMedia = media != null && media.length > 0;
|
||||
if (hasMedia && (adapter.isSensitiveContentEnabled() || !sensitive)) {
|
||||
mediaPreview.setVisibility(hasMedia ? View.VISIBLE : View.GONE);
|
||||
mediaPreview.displayMedia(media, loader, account_id, this, adapter.getImageLoadingHandler());
|
||||
mediaPreview.displayMedia(media, loader, account_id, this, adapter.getMediaLoadingHandler());
|
||||
} else {
|
||||
mediaPreview.setVisibility(View.GONE);
|
||||
}
|
||||
|
@ -528,7 +529,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
@Override
|
||||
public void onClick(View v) {
|
||||
if (statusClickListener == null) return;
|
||||
final int position = getAdapterPosition();
|
||||
final int position = getLayoutPosition();
|
||||
switch (v.getId()) {
|
||||
case R.id.item_content: {
|
||||
statusClickListener.onStatusClick(this, position);
|
||||
|
@ -551,10 +552,22 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (statusClickListener == null) return false;
|
||||
final int position = getLayoutPosition();
|
||||
switch (v.getId()) {
|
||||
case R.id.item_content: {
|
||||
return statusClickListener.onStatusLongClick(this, position);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaClick(View view, ParcelableMedia media, long accountId) {
|
||||
if (statusClickListener == null) return;
|
||||
final int position = getAdapterPosition();
|
||||
final int position = getLayoutPosition();
|
||||
statusClickListener.onMediaClick(this, media, position);
|
||||
}
|
||||
|
||||
|
@ -564,10 +577,10 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
|
||||
public void setStatusClickListener(StatusClickListener listener) {
|
||||
statusClickListener = listener;
|
||||
itemView.findViewById(R.id.item_content).setOnClickListener(this);
|
||||
((View) itemContent).setOnClickListener(this);
|
||||
((View) itemContent).setOnLongClickListener(this);
|
||||
|
||||
itemMenu.setOnClickListener(this);
|
||||
itemView.setOnClickListener(this);
|
||||
profileImageView.setOnClickListener(this);
|
||||
replyCountView.setOnClickListener(this);
|
||||
retweetCountView.setOnClickListener(this);
|
||||
|
@ -630,12 +643,12 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
|
||||
public static interface StatusClickListener extends ContentCardClickListener {
|
||||
|
||||
boolean isProfileImageEnabled();
|
||||
|
||||
void onMediaClick(StatusViewHolder holder, ParcelableMedia media, int position);
|
||||
|
||||
void onStatusClick(StatusViewHolder holder, int position);
|
||||
|
||||
boolean onStatusLongClick(StatusViewHolder holder, int position);
|
||||
|
||||
void onUserProfileClick(StatusViewHolder holder, int position);
|
||||
}
|
||||
|
||||
|
@ -644,7 +657,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
private final Context context;
|
||||
private final SharedPreferencesWrapper preferences;
|
||||
private final MediaLoaderWrapper loader;
|
||||
private final ImageLoadingHandler handler;
|
||||
private final MediaLoadingHandler handler;
|
||||
private final AsyncTwitterWrapper twitter;
|
||||
private final TwidereLinkify linkify;
|
||||
private int profileImageStyle;
|
||||
|
@ -662,14 +675,14 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
preferences = SharedPreferencesWrapper.getInstance(context, SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
final TwidereApplication app = TwidereApplication.getInstance(context);
|
||||
loader = app.getMediaLoaderWrapper();
|
||||
handler = new ImageLoadingHandler(R.id.media_preview_progress);
|
||||
handler = new MediaLoadingHandler(R.id.media_preview_progress);
|
||||
twitter = app.getTwitterWrapper();
|
||||
linkify = new TwidereLinkify(null);
|
||||
updateOptions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaLoaderWrapper getImageLoader() {
|
||||
public MediaLoaderWrapper getMediaLoader() {
|
||||
return loader;
|
||||
}
|
||||
|
||||
|
@ -679,7 +692,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
}
|
||||
|
||||
@Override
|
||||
public ImageLoadingHandler getImageLoadingHandler() {
|
||||
public MediaLoadingHandler getMediaLoadingHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
|
@ -698,6 +711,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
return mediaPreviewStyle;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AsyncTwitterWrapper getTwitterWrapper() {
|
||||
return twitter;
|
||||
|
@ -807,6 +821,11 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStatusLongClick(StatusViewHolder holder, int position) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaClick(StatusViewHolder holder, ParcelableMedia media, int position) {
|
||||
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* 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.view.holder;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.adapter.iface.IContentCardAdapter;
|
||||
import org.mariotaku.twidere.model.ParcelableUser;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.view.iface.IColorLabelView;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.mariotaku.twidere.util.UserColorNameUtils.getUserColor;
|
||||
import static org.mariotaku.twidere.util.UserColorNameUtils.getUserNickname;
|
||||
import static org.mariotaku.twidere.util.Utils.getLocalizedNumber;
|
||||
import static org.mariotaku.twidere.util.Utils.getUserTypeIconRes;
|
||||
|
||||
public class UserViewHolder extends ViewHolder {
|
||||
|
||||
private final IContentCardAdapter adapter;
|
||||
|
||||
public final IColorLabelView content;
|
||||
private final ImageView profileImageView, profileTypeView;
|
||||
private final TextView name, screenName, description, location, url, statusesCount, followersCount,
|
||||
friendsCount;
|
||||
private boolean account_color_enabled;
|
||||
|
||||
public UserViewHolder(final IContentCardAdapter adapter, final View itemView) {
|
||||
super(itemView);
|
||||
this.adapter = adapter;
|
||||
content = (IColorLabelView) itemView.findViewById(R.id.content);
|
||||
profileImageView = (ImageView) itemView.findViewById(R.id.profile_image);
|
||||
profileTypeView = (ImageView) itemView.findViewById(R.id.profile_type);
|
||||
name = (TextView) itemView.findViewById(R.id.name);
|
||||
screenName = (TextView) itemView.findViewById(R.id.screen_name);
|
||||
description = (TextView) itemView.findViewById(R.id.description);
|
||||
location = (TextView) itemView.findViewById(R.id.location);
|
||||
url = (TextView) itemView.findViewById(R.id.url);
|
||||
statusesCount = (TextView) itemView.findViewById(R.id.statuses_count);
|
||||
followersCount = (TextView) itemView.findViewById(R.id.followers_count);
|
||||
friendsCount = (TextView) itemView.findViewById(R.id.friends_count);
|
||||
}
|
||||
|
||||
public void setAccountColor(final int color) {
|
||||
content.drawEnd(account_color_enabled ? color : Color.TRANSPARENT);
|
||||
}
|
||||
|
||||
public void setAccountColorEnabled(final boolean enabled) {
|
||||
account_color_enabled = enabled;
|
||||
if (!account_color_enabled) {
|
||||
content.drawEnd(Color.TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
public void setHighlightColor(final int color) {
|
||||
content.drawBackground(color);
|
||||
}
|
||||
|
||||
public void setTextSize(final float textSize) {
|
||||
description.setTextSize(textSize);
|
||||
name.setTextSize(textSize);
|
||||
screenName.setTextSize(textSize * 0.75f);
|
||||
location.setTextSize(textSize);
|
||||
url.setTextSize(textSize);
|
||||
statusesCount.setTextSize(textSize);
|
||||
followersCount.setTextSize(textSize);
|
||||
friendsCount.setTextSize(textSize);
|
||||
}
|
||||
|
||||
public void displayUser(ParcelableUser user) {
|
||||
|
||||
final Context context = adapter.getContext();
|
||||
final MediaLoaderWrapper loader = adapter.getMediaLoader();
|
||||
|
||||
|
||||
setUserColor(getUserColor(context, user.id));
|
||||
|
||||
final int userTypeRes = getUserTypeIconRes(user.is_verified, user.is_protected);
|
||||
if (userTypeRes != 0) {
|
||||
profileTypeView.setImageResource(userTypeRes);
|
||||
} else {
|
||||
profileTypeView.setImageDrawable(null);
|
||||
}
|
||||
name.setText(getUserNickname(context, user.id, user.name));
|
||||
screenName.setText("@" + user.screen_name);
|
||||
description.setVisibility(TextUtils.isEmpty(user.description_unescaped) ? View.GONE : View.VISIBLE);
|
||||
description.setText(user.description_unescaped);
|
||||
location.setVisibility(TextUtils.isEmpty(user.location) ? View.GONE : View.VISIBLE);
|
||||
location.setText(user.location);
|
||||
url.setVisibility(TextUtils.isEmpty(user.url_expanded) ? View.GONE : View.VISIBLE);
|
||||
url.setText(user.url_expanded);
|
||||
final Locale locale = Locale.getDefault();
|
||||
statusesCount.setText(getLocalizedNumber(locale, user.statuses_count));
|
||||
followersCount.setText(getLocalizedNumber(locale, user.followers_count));
|
||||
friendsCount.setText(getLocalizedNumber(locale, user.friends_count));
|
||||
if (adapter.isProfileImageEnabled()) {
|
||||
profileImageView.setVisibility(View.VISIBLE);
|
||||
loader.displayProfileImage(profileImageView, user.profile_image_url);
|
||||
} else {
|
||||
profileImageView.setVisibility(View.GONE);
|
||||
loader.cancelDisplayTask(profileImageView);
|
||||
}
|
||||
}
|
||||
|
||||
public void setUserColor(final int color) {
|
||||
content.drawStart(color);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue