improved settings ui

improved base theme
started to redesign all timeline fragments.
This commit is contained in:
Mariotaku Lee 2014-12-03 18:27:11 +08:00
parent 8c39dc280f
commit 4cc47a3af1
81 changed files with 3728 additions and 2781 deletions

View File

@ -28,7 +28,7 @@ package org.mariotaku.twidere;
public interface Constants extends TwidereConstants {
public static final String DATABASES_NAME = "twidere.sqlite";
public static final int DATABASES_VERSION = 72;
public static final int DATABASES_VERSION = 74;
public static final int MENU_GROUP_STATUS_EXTENSION = 10;
public static final int MENU_GROUP_COMPOSE_EXTENSION = 11;

View File

@ -31,23 +31,30 @@ import android.graphics.PorterDuff.Mode;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.ViewParent;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.support.DataExportActivity;
import org.mariotaku.twidere.activity.support.DataImportActivity;
import org.mariotaku.twidere.adapter.ArrayAdapter;
import org.mariotaku.twidere.graphic.EmptyDrawable;
import org.mariotaku.twidere.util.CompareUtils;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.view.holder.ViewHolder;
import java.util.ArrayList;
import java.util.List;
public class SettingsActivity extends BasePreferenceActivity {
@ -60,7 +67,7 @@ public class SettingsActivity extends BasePreferenceActivity {
private HeaderAdapter mAdapter;
private int mCurrentThemeColor, mThemeBackgroundAlpha;
private boolean mCompactCards, mPlainListStyle;
private boolean mCompactCards;
private String mTheme;
private String mThemeFontFamily;
@ -179,7 +186,6 @@ public class SettingsActivity extends BasePreferenceActivity {
mPackageManager = getPackageManager();
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE);
mCompactCards = mPreferences.getBoolean(KEY_COMPACT_CARDS, false);
mPlainListStyle = mPreferences.getBoolean(KEY_PLAIN_LIST_STYLE, false);
mTheme = mPreferences.getString(KEY_THEME, DEFAULT_THEME);
mThemeBackground = mPreferences.getString(KEY_THEME_BACKGROUND, DEFAULT_THEME_BACKGROUND);
mThemeBackgroundAlpha = mPreferences.getInt(KEY_THEME_BACKGROUND_ALPHA, DEFAULT_THEME_BACKGROUND_ALPHA);
@ -194,6 +200,24 @@ public class SettingsActivity extends BasePreferenceActivity {
if (savedInstanceState != null) {
invalidateHeaders();
}
final ListView listView = getListView();
if (listView != null) {
listView.setDivider(new EmptyDrawable());
listView.setDividerHeight(0);
final LayoutParams lp = listView.getLayoutParams();
if (lp instanceof MarginLayoutParams) {
final MarginLayoutParams mlp = (MarginLayoutParams) lp;
mlp.leftMargin = 0;
mlp.topMargin = 0;
mlp.rightMargin = 0;
mlp.bottomMargin = 0;
listView.setLayoutParams(mlp);
}
final ViewParent listParent = listView.getParent();
if (listParent instanceof ViewGroup) {
((ViewGroup) listParent).setPadding(0, 0, 0, 0);
}
}
}
private boolean shouldNotifyThemeChange() {
@ -202,91 +226,199 @@ public class SettingsActivity extends BasePreferenceActivity {
|| !CompareUtils.objectEquals(mThemeBackground, mPreferences.getString(KEY_THEME_BACKGROUND, DEFAULT_THEME_BACKGROUND))
|| mCurrentThemeColor != ThemeUtils.getUserAccentColor(this)
|| mThemeBackgroundAlpha != mPreferences.getInt(KEY_THEME_BACKGROUND_ALPHA, DEFAULT_THEME_BACKGROUND_ALPHA)
|| mCompactCards != mPreferences.getBoolean(KEY_COMPACT_CARDS, false)
|| mPlainListStyle != mPreferences.getBoolean(KEY_PLAIN_LIST_STYLE, false);
|| mCompactCards != mPreferences.getBoolean(KEY_COMPACT_CARDS, false);
}
private static class HeaderAdapter extends ArrayAdapter<Header> {
private static class HeaderAdapter extends BaseAdapter {
static final int HEADER_TYPE_CATEGORY = 0;
static final int HEADER_TYPE_NORMAL = 1;
static final int HEADER_TYPE_NORMAL = 0;
static final int HEADER_TYPE_CATEGORY = 1;
static final int HEADER_TYPE_SPACE = 2;
private final Context mContext;
private final Resources mResources;
private final int mActionIconColor;
private final ArrayList<Header> mHeaders;
private final LayoutInflater mInflater;
private int mCategoriesCount;
private boolean mFirstItemIsCategory;
public HeaderAdapter(final Context context) {
super(context, R.layout.list_item_preference_header);
mContext = context;
mInflater = LayoutInflater.from(context);
mHeaders = new ArrayList<>();
mResources = context.getResources();
mActionIconColor = ThemeUtils.getThemeForegroundColor(context);
}
public void add(Header header) {
mHeaders.add(header);
notifyDataSetChanged();
}
public void addAll(List<Header> headers) {
mHeaders.addAll(headers);
notifyDataSetChanged();
}
@Override
public boolean areAllItemsEnabled() {
return false;
}
@Override
public void notifyDataSetChanged() {
updateCategoriesInfo();
super.notifyDataSetChanged();
}
private void updateCategoriesInfo() {
mFirstItemIsCategory = !mHeaders.isEmpty()
&& getHeaderType(mHeaders.get(0)) == HEADER_TYPE_CATEGORY;
mCategoriesCount = getCategoriesCount(0, mHeaders.size());
}
private int getCategoriesCount(final int start, final int end) {
int categoriesCount = 0;
for (int i = start; i < end; i++) {
if (getHeaderType(mHeaders.get(i)) == HEADER_TYPE_CATEGORY) {
categoriesCount++;
}
}
return categoriesCount;
}
public void clear() {
mHeaders.clear();
notifyDataSetChanged();
}
@Override
public int getViewTypeCount() {
return 3;
}
@Override
public int getItemViewType(final int position) {
final Header header = getItem(position);
return getHeaderType(header);
}
@Override
public int getCount() {
return mHeaders.size() + mCategoriesCount + (mFirstItemIsCategory ? 0 : 1);
}
@Override
public Header getItem(final int position) {
if (position == getCount() - 1) return new Header();
final int realPosition = mFirstItemIsCategory ? position + 1 : position;
int categoriesCount = 0;
int i;
for (i = 0; i + categoriesCount < realPosition; i++) {
if (getHeaderType(mHeaders.get(i)) == HEADER_TYPE_CATEGORY) {
categoriesCount++;
}
}
if (i + categoriesCount == realPosition && getHeaderType(mHeaders.get(i)) == HEADER_TYPE_CATEGORY) {
return new Header();
}
return mHeaders.get(realPosition - categoriesCount);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
final Header header = getItem(position);
final int viewType = getHeaderType(header);
final View view;
final View view = convertView != null ? convertView : inflateItemView(viewType, parent);
switch (viewType) {
case HEADER_TYPE_CATEGORY: {
view = new TextView(mContext, null, android.R.attr.listSeparatorTextViewStyle);
((TextView) view).setText(header.getTitle(mResources));
bindCategoryHeader(view, position, header);
break;
}
case HEADER_TYPE_SPACE: {
break;
}
default: {
final boolean viewChanged = convertView != null
&& !(convertView.getTag() instanceof HeaderViewHolder);
view = super.getView(position, viewChanged ? null : convertView, parent);
final HeaderViewHolder holder;
final Object tag = view.getTag();
if (tag instanceof HeaderViewHolder) {
holder = (HeaderViewHolder) tag;
} else {
holder = new HeaderViewHolder(view);
view.setTag(holder);
}
final CharSequence title = header.getTitle(mResources);
holder.title.setText(title);
final CharSequence summary = header.getSummary(mResources);
if (!TextUtils.isEmpty(summary)) {
holder.summary.setVisibility(View.VISIBLE);
holder.summary.setText(summary);
} else {
holder.summary.setVisibility(View.GONE);
}
if (header.iconRes != 0) {
holder.icon.setImageResource(header.iconRes);
} else {
holder.icon.setImageDrawable(null);
}
holder.icon.setColorFilter(mActionIconColor, Mode.SRC_ATOP);
bindHeader(view, position, header);
break;
}
}
return view;
}
private void bindCategoryHeader(View view, int position, Header header) {
final TextView title = (TextView) view.findViewById(android.R.id.title);
if (!TextUtils.isEmpty(header.title)) {
title.setText(header.title);
} else {
title.setText(header.titleRes);
}
}
private void bindHeader(View view, int position, Header header) {
final HeaderViewHolder holder;
final Object tag = view.getTag();
if (tag instanceof HeaderViewHolder) {
holder = (HeaderViewHolder) tag;
} else {
holder = new HeaderViewHolder(view);
view.setTag(holder);
}
final CharSequence title = header.getTitle(mResources);
holder.title.setText(title);
final CharSequence summary = header.getSummary(mResources);
if (!TextUtils.isEmpty(summary)) {
holder.summary.setVisibility(View.VISIBLE);
holder.summary.setText(summary);
} else {
holder.summary.setVisibility(View.GONE);
}
if (header.iconRes != 0) {
holder.icon.setImageResource(header.iconRes);
} else {
holder.icon.setImageDrawable(null);
}
holder.icon.setColorFilter(mActionIconColor, Mode.SRC_ATOP);
}
private View inflateItemView(int viewType, ViewGroup parent) {
final int layoutRes;
switch (viewType) {
case HEADER_TYPE_CATEGORY: {
layoutRes = R.layout.list_item_preference_header_category;
break;
}
case HEADER_TYPE_SPACE: {
layoutRes = R.layout.list_item_preference_header_space;
break;
}
default: {
layoutRes = R.layout.list_item_preference_header_item;
break;
}
}
return mInflater.inflate(layoutRes, parent, false);
}
@Override
public boolean isEnabled(final int position) {
return getItemViewType(position) != HEADER_TYPE_CATEGORY;
return getItemViewType(position) == HEADER_TYPE_NORMAL;
}
private static int getHeaderType(final Header header) {
if (header.fragment == null && header.intent == null)
if (header.fragment != null || header.intent != null)
return HEADER_TYPE_NORMAL;
else if (header.title != null || header.titleRes != 0)
return HEADER_TYPE_CATEGORY;
else
return HEADER_TYPE_NORMAL;
return HEADER_TYPE_SPACE;
}
private static class HeaderViewHolder extends ViewHolder {

View File

@ -801,7 +801,7 @@ public class HomeActivity extends BaseSupportActivity implements OnClickListener
final Window window = getWindow();
final Drawable windowBackground = ThemeUtils.getWindowBackground(this, getCurrentThemeResourceId());
ViewAccessor.setBackground(mSlidingMenu.getContent(), windowBackground);
window.setBackgroundDrawable(new EmptyDrawable());
window.setBackgroundDrawable(new EmptyDrawable(windowBackground));
}
private void showDataProfilingRequest() {
@ -918,6 +918,8 @@ public class HomeActivity extends BaseSupportActivity implements OnClickListener
if (fragment instanceof AccountsDashboardFragment) {
((AccountsDashboardFragment) fragment).setStatusBarHeight(insets.top);
}
//TODO
mColorStatusFrameLayout.setStatusBarHeight(insets.top);
}

View File

@ -203,13 +203,25 @@ public class LinkHandlerActivity extends BaseSupportActivity implements OnClickL
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
window.addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
final int transitionRes;
switch (linkId) {
case LINK_ID_USER: {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !ThemeUtils.isTransparentBackground(this)) {
Utils.setSharedElementTransition(this, window, R.transition.transition_user_profile);
}
transitionRes = R.transition.transition_user;
break;
}
case LINK_ID_STATUS: {
// transitionRes = R.transition.transition_status;
transitionRes = 0;
break;
}
default: {
transitionRes = 0;
break;
}
}
if (transitionRes != 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
&& !ThemeUtils.isTransparentBackground(this)) {
Utils.setSharedElementTransition(this, window, R.transition.transition_status);
}
}

View File

@ -1,27 +1,39 @@
package org.mariotaku.twidere.adapter;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.util.Pair;
import android.support.v7.widget.RecyclerView.Adapter;
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.IStatusesAdapter;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.view.holder.LoadIndicatorViewHolder;
import org.mariotaku.twidere.fragment.support.StatusFragment;
import org.mariotaku.twidere.fragment.support.StatusMenuDialogFragment;
import org.mariotaku.twidere.fragment.support.UserFragment;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.ImageLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.view.holder.GapViewHolder;
import org.mariotaku.twidere.view.holder.LoadIndicatorViewHolder;
import org.mariotaku.twidere.view.holder.StatusViewHolder;
/**
* Created by mariotaku on 14/11/19.
*/
public abstract class AbsStatusesAdapter extends Adapter<ViewHolder> implements IStatusesAdapter {
* Created by mariotaku on 14/11/19.
*/
public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implements Constants,
IStatusesAdapter<D> {
private static final int ITEM_VIEW_TYPE_STATUS = 1;
private static final int ITEM_VIEW_TYPE_LOAD_INDICATOR = 2;
private static final int ITEM_VIEW_TYPE_GAP = 2;
private static final int ITEM_VIEW_TYPE_LOAD_INDICATOR = 3;
private final Context mContext;
private final LayoutInflater mInflater;
@ -30,7 +42,7 @@ public abstract class AbsStatusesAdapter extends Adapter<ViewHolder> implements
private final int mCardLayoutResource;
private boolean mLoadMoreIndicatorEnabled;
public AbsStatusesAdapter(Context context, boolean compact) {
public AbsStatusesAdapter(Context context, boolean compact) {
mContext = context;
mInflater = LayoutInflater.from(context);
mImageLoader = TwidereApplication.getInstance(context).getImageLoaderWrapper();
@ -47,7 +59,11 @@ public abstract class AbsStatusesAdapter extends Adapter<ViewHolder> implements
switch (viewType) {
case ITEM_VIEW_TYPE_STATUS: {
final View view = mInflater.inflate(mCardLayoutResource, parent, false);
return new StatusViewHolder(this, view);
return new StatusViewHolder<>(this, view);
}
case ITEM_VIEW_TYPE_GAP: {
final View view = mInflater.inflate(R.layout.card_item_gap, parent, false);
return new GapViewHolder(this, view);
}
case ITEM_VIEW_TYPE_LOAD_INDICATOR: {
final View view = mInflater.inflate(R.layout.card_item_load_indicator, parent, false);
@ -83,6 +99,8 @@ public abstract class AbsStatusesAdapter extends Adapter<ViewHolder> implements
public int getItemViewType(int position) {
if (position == getItemCount() - 1) {
return ITEM_VIEW_TYPE_LOAD_INDICATOR;
} else if (isGapItem(position)) {
return ITEM_VIEW_TYPE_GAP;
}
return ITEM_VIEW_TYPE_STATUS;
}
@ -107,5 +125,46 @@ public abstract class AbsStatusesAdapter extends Adapter<ViewHolder> implements
return mLoadingHandler;
}
@Override
public void onStatusClick(StatusViewHolder holder, int position) {
final Context context = getContext();
// final View cardView = holder.getCardView();
// if (cardView != null && context instanceof FragmentActivity) {
// final Bundle options = Utils.makeSceneTransitionOption((FragmentActivity) context,
// new Pair<>(cardView, StatusFragment.TRANSITION_NAME_CARD));
// Utils.openStatus(context, getStatus(position), options);
// } else {
Utils.openStatus(context, getStatus(position), null);
// }
}
@Override
public void onUserProfileClick(StatusViewHolder holder, int position) {
final Context context = getContext();
final ParcelableStatus status = getStatus(position);
final View profileImageView = holder.getProfileImageView();
if (context instanceof FragmentActivity) {
final Bundle options = Utils.makeSceneTransitionOption((FragmentActivity) context,
new Pair<>(profileImageView, UserFragment.TRANSITION_NAME_PROFILE_IMAGE));
Utils.openUserProfile(context, status.account_id, status.user_id, status.user_screen_name, options);
} else {
Utils.openUserProfile(context, status.account_id, status.user_id, status.user_screen_name, null);
}
}
@Override
public void onItemMenuClick(StatusViewHolder holder, int position) {
final Context context = getContext();
if (!(context instanceof FragmentActivity)) return;
final Bundle args = new Bundle();
args.putParcelable(EXTRA_STATUS, getStatus(position));
final StatusMenuDialogFragment f = new StatusMenuDialogFragment();
f.setArguments(args);
f.show(((FragmentActivity) context).getSupportFragmentManager(), "status_menu");
}
public abstract void setData(D data);
public abstract D getData();
}

View File

@ -19,12 +19,6 @@
package org.mariotaku.twidere.adapter;
import static org.mariotaku.twidere.util.Utils.configBaseCardAdapter;
import static org.mariotaku.twidere.util.Utils.getAccountColor;
import static org.mariotaku.twidere.util.Utils.getDisplayName;
import static org.mariotaku.twidere.util.Utils.isCompactCards;
import static org.mariotaku.twidere.util.Utils.isPlainListStyle;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
@ -42,196 +36,195 @@ import org.mariotaku.twidere.view.holder.ActivityListViewHolder;
import java.util.List;
import static org.mariotaku.twidere.util.Utils.configBaseCardAdapter;
import static org.mariotaku.twidere.util.Utils.getAccountColor;
import static org.mariotaku.twidere.util.Utils.getDisplayName;
import static org.mariotaku.twidere.util.Utils.isCompactCards;
public abstract class BaseParcelableActivitiesAdapter extends BaseArrayAdapter<ParcelableActivity> implements
IBaseCardAdapter {
IBaseCardAdapter {
private final MultiSelectManager mMultiSelectManager;
private final ImageLoaderWrapper mImageLoader;
private final MultiSelectManager mMultiSelectManager;
private final ImageLoaderWrapper mImageLoader;
private boolean mShowAbsoluteTime, mAnimationEnabled;
private int mMaxAnimationPosition;
private boolean mShowAbsoluteTime, mAnimationEnabled;
private int mMaxAnimationPosition;
private MenuButtonClickListener mListener;
private final boolean mPlainList;
private MenuButtonClickListener mListener;
public BaseParcelableActivitiesAdapter(final Context context) {
this(context, isCompactCards(context), isPlainListStyle(context));
}
public BaseParcelableActivitiesAdapter(final Context context) {
this(context, isCompactCards(context));
}
public BaseParcelableActivitiesAdapter(final Context context, final boolean compactCards, final boolean plainList) {
super(context, getItemResource(compactCards));
mPlainList = plainList;
final TwidereApplication app = TwidereApplication.getInstance(context);
mMultiSelectManager = app.getMultiSelectManager();
mImageLoader = app.getImageLoaderWrapper();
configBaseCardAdapter(context, this);
}
public BaseParcelableActivitiesAdapter(final Context context, final boolean compactCards) {
super(context, getItemResource(compactCards));
final TwidereApplication app = TwidereApplication.getInstance(context);
mMultiSelectManager = app.getMultiSelectManager();
mImageLoader = app.getImageLoaderWrapper();
configBaseCardAdapter(context, this);
}
public abstract void bindView(final int position, final ActivityListViewHolder holder, final ParcelableActivity item);
public abstract void bindView(final int position, final ActivityListViewHolder holder, final ParcelableActivity item);
@Override
public ImageLoaderWrapper getImageLoader() {
return mImageLoader;
}
@Override
public ImageLoaderWrapper getImageLoader() {
return mImageLoader;
}
@Override
public long getItemId(final int position) {
final Object obj = getItem(position);
return obj != null ? obj.hashCode() : 0;
}
@Override
public long getItemId(final int position) {
final Object obj = getItem(position);
return obj != null ? obj.hashCode() : 0;
}
@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 ActivityListViewHolder holder = tag instanceof ActivityListViewHolder ? (ActivityListViewHolder) tag
: new ActivityListViewHolder(view);
if (!(tag instanceof ActivityListViewHolder)) {
if (mPlainList) {
((View) holder.content).setPadding(0, 0, 0, 0);
holder.content.setItemBackground(null);
}
view.setTag(holder);
}
@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 ActivityListViewHolder holder = tag instanceof ActivityListViewHolder ? (ActivityListViewHolder) tag
: new ActivityListViewHolder(view);
if (!(tag instanceof ActivityListViewHolder)) {
view.setTag(holder);
}
final boolean showAccountColor = isShowAccountColor();
final boolean showAccountColor = isShowAccountColor();
holder.setTextSize(getTextSize());
holder.my_profile_image.setVisibility(View.GONE);
final ParcelableActivity item = getItem(position);
holder.setAccountColorEnabled(showAccountColor);
if (showAccountColor) {
holder.setAccountColor(getAccountColor(getContext(), item.account_id));
}
if (mShowAbsoluteTime) {
holder.time.setTime(item.activity_timestamp);
} else {
holder.time.setTime(item.activity_timestamp);
}
bindView(position, holder, item);
return view;
}
holder.setTextSize(getTextSize());
holder.my_profile_image.setVisibility(View.GONE);
final ParcelableActivity item = getItem(position);
holder.setAccountColorEnabled(showAccountColor);
if (showAccountColor) {
holder.setAccountColor(getAccountColor(getContext(), item.account_id));
}
if (mShowAbsoluteTime) {
holder.time.setTime(item.activity_timestamp);
} else {
holder.time.setTime(item.activity_timestamp);
}
bindView(position, holder, item);
return view;
}
public void onItemSelected(final Object item) {
notifyDataSetChanged();
}
public void onItemSelected(final Object item) {
notifyDataSetChanged();
}
public void onItemUnselected(final Object item) {
notifyDataSetChanged();
}
public void onItemUnselected(final Object item) {
notifyDataSetChanged();
}
@Override
public void setAnimationEnabled(final boolean anim) {
if (mAnimationEnabled == anim) return;
mAnimationEnabled = anim;
}
@Override
public void setAnimationEnabled(final boolean anim) {
if (mAnimationEnabled == anim) return;
mAnimationEnabled = anim;
}
public void setData(final List<ParcelableActivity> data) {
clear();
if (data == null) return;
addAll(data);
}
public void setData(final List<ParcelableActivity> data) {
clear();
if (data == null) return;
addAll(data);
}
@Override
public void setMaxAnimationPosition(final int position) {
mMaxAnimationPosition = position;
}
@Override
public void setMaxAnimationPosition(final int position) {
mMaxAnimationPosition = position;
}
@Override
public void setMenuButtonClickListener(final MenuButtonClickListener listener) {
mListener = listener;
}
@Override
public void setMenuButtonClickListener(final MenuButtonClickListener listener) {
mListener = listener;
}
public void setShowAbsoluteTime(final boolean show) {
if (show != mShowAbsoluteTime) {
mShowAbsoluteTime = show;
notifyDataSetChanged();
}
}
public void setShowAbsoluteTime(final boolean show) {
if (show != mShowAbsoluteTime) {
mShowAbsoluteTime = show;
notifyDataSetChanged();
}
}
protected void displayActivityUserProfileImages(final ActivityListViewHolder holder, final ParcelableStatus[] statuses) {
if (statuses == null) {
displayActivityUserProfileImages(holder, new String[0]);
} else {
final String[] urls = new String[statuses.length];
for (int i = 0, j = statuses.length; i < j; i++) {
urls[i] = statuses[i].user_profile_image_url;
}
displayActivityUserProfileImages(holder, urls);
}
}
protected void displayActivityUserProfileImages(final ActivityListViewHolder holder, final ParcelableStatus[] statuses) {
if (statuses == null) {
displayActivityUserProfileImages(holder, new String[0]);
} else {
final String[] urls = new String[statuses.length];
for (int i = 0, j = statuses.length; i < j; i++) {
urls[i] = statuses[i].user_profile_image_url;
}
displayActivityUserProfileImages(holder, urls);
}
}
protected void displayActivityUserProfileImages(final ActivityListViewHolder holder, final ParcelableUser[] users) {
if (users == null) {
displayActivityUserProfileImages(holder, new String[0]);
} else {
final String[] urls = new String[users.length];
for (int i = 0, j = users.length; i < j; i++) {
urls[i] = users[i].profile_image_url;
}
displayActivityUserProfileImages(holder, urls);
}
}
protected void displayActivityUserProfileImages(final ActivityListViewHolder holder, final ParcelableUser[] users) {
if (users == null) {
displayActivityUserProfileImages(holder, new String[0]);
} else {
final String[] urls = new String[users.length];
for (int i = 0, j = users.length; i < j; i++) {
urls[i] = users[i].profile_image_url;
}
displayActivityUserProfileImages(holder, urls);
}
}
protected void displayProfileImage(final ImageView view, final ParcelableUser user) {
if (isDisplayProfileImage()) {
mImageLoader.displayProfileImage(view, user.profile_image_url);
} else {
view.setImageDrawable(null);
}
}
protected void displayProfileImage(final ImageView view, final ParcelableUser user) {
if (isDisplayProfileImage()) {
mImageLoader.displayProfileImage(view, user.profile_image_url);
} else {
view.setImageDrawable(null);
}
}
protected String getName(final ParcelableStatus status) {
if (status == null) return null;
return getDisplayName(getContext(), status.user_id, status.user_name, status.user_screen_name,
isDisplayNameFirst(), isNicknameOnly());
}
protected String getName(final ParcelableStatus status) {
if (status == null) return null;
return getDisplayName(getContext(), status.user_id, status.user_name, status.user_screen_name,
isDisplayNameFirst(), isNicknameOnly());
}
protected String getName(final ParcelableUser user) {
if (user == null) return null;
return getDisplayName(getContext(), user.id, user.name, user.screen_name, isDisplayNameFirst(),
isNicknameOnly());
}
protected String getName(final ParcelableUser user) {
if (user == null) return null;
return getDisplayName(getContext(), user.id, user.name, user.screen_name, isDisplayNameFirst(),
isNicknameOnly());
}
protected void setProfileImage(final ImageView view, final ParcelableStatus status) {
if (isDisplayProfileImage()) {
mImageLoader.displayProfileImage(view, status.user_profile_image_url);
} else {
view.setImageDrawable(null);
}
}
protected void setProfileImage(final ImageView view, final ParcelableStatus status) {
if (isDisplayProfileImage()) {
mImageLoader.displayProfileImage(view, status.user_profile_image_url);
} else {
view.setImageDrawable(null);
}
}
protected boolean shouldDisplayProfileImage() {
return isDisplayProfileImage();
}
protected boolean shouldDisplayProfileImage() {
return isDisplayProfileImage();
}
private void displayActivityUserProfileImages(final ActivityListViewHolder holder, final String[] urls) {
final int length = urls != null ? Math.min(holder.activity_profile_images.length, urls.length) : 0;
final boolean shouldDisplayImages = isDisplayProfileImage() && length > 0;
holder.activity_profile_images_container.setVisibility(shouldDisplayImages ? View.VISIBLE : View.GONE);
if (!shouldDisplayImages) return;
for (int i = 0, j = holder.activity_profile_images.length; i < j; i++) {
final ImageView view = holder.activity_profile_images[i];
view.setImageDrawable(null);
if (i < length) {
view.setVisibility(View.VISIBLE);
mImageLoader.displayProfileImage(view, urls[i]);
} else {
private void displayActivityUserProfileImages(final ActivityListViewHolder holder, final String[] urls) {
final int length = urls != null ? Math.min(holder.activity_profile_images.length, urls.length) : 0;
final boolean shouldDisplayImages = isDisplayProfileImage() && length > 0;
holder.activity_profile_images_container.setVisibility(shouldDisplayImages ? View.VISIBLE : View.GONE);
if (!shouldDisplayImages) return;
for (int i = 0, j = holder.activity_profile_images.length; i < j; i++) {
final ImageView view = holder.activity_profile_images[i];
view.setImageDrawable(null);
if (i < length) {
view.setVisibility(View.VISIBLE);
mImageLoader.displayProfileImage(view, urls[i]);
} else {
mImageLoader.cancelDisplayTask(view);
view.setVisibility(View.GONE);
}
}
if (urls.length > holder.activity_profile_images.length) {
final int moreNumber = urls.length - holder.activity_profile_images.length;
holder.activity_profile_image_more_number.setVisibility(View.VISIBLE);
holder.activity_profile_image_more_number.setText(getContext().getString(R.string.and_more, moreNumber));
} else {
holder.activity_profile_image_more_number.setVisibility(View.GONE);
}
}
view.setVisibility(View.GONE);
}
}
if (urls.length > holder.activity_profile_images.length) {
final int moreNumber = urls.length - holder.activity_profile_images.length;
holder.activity_profile_image_more_number.setVisibility(View.VISIBLE);
holder.activity_profile_image_more_number.setText(getContext().getString(R.string.and_more, moreNumber));
} else {
holder.activity_profile_image_more_number.setVisibility(View.GONE);
}
}
private static int getItemResource(final boolean compactCards) {
return compactCards ? R.layout.card_item_activity_compact : R.layout.card_item_activity;
}
private static int getItemResource(final boolean compactCards) {
return compactCards ? R.layout.card_item_activity_compact : R.layout.card_item_activity;
}
}

View File

@ -1,517 +1,85 @@
/*
* Twidere - Twitter client for Android
*
* 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;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v4.util.Pair;
import android.text.Html;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView.ScaleType;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.fragment.support.UserFragment;
import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableUserMention;
import org.mariotaku.twidere.provider.TweetStore.Statuses;
import org.mariotaku.twidere.util.ImageLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.MultiSelectManager;
import org.mariotaku.twidere.util.TwidereLinkify;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.view.holder.StatusListViewHolder;
import org.mariotaku.twidere.view.iface.ICardItemView.OnOverflowIconClickListener;
import org.mariotaku.twidere.model.ParcelableStatus.CursorIndices;
import org.mariotaku.twidere.view.holder.StatusViewHolder;
import java.util.Locale;
/**
* Created by mariotaku on 14/11/19.
*/
public class CursorStatusesAdapter extends AbsStatusesAdapter<Cursor> {
import static org.mariotaku.twidere.util.UserColorNicknameUtils.getUserColor;
import static org.mariotaku.twidere.util.UserColorNicknameUtils.getUserNickname;
import static org.mariotaku.twidere.util.Utils.configBaseCardAdapter;
import static org.mariotaku.twidere.util.Utils.findStatusInDatabases;
import static org.mariotaku.twidere.util.Utils.getAccountColor;
import static org.mariotaku.twidere.util.Utils.getCardHighlightColor;
import static org.mariotaku.twidere.util.Utils.getCardHighlightOptionInt;
import static org.mariotaku.twidere.util.Utils.isFiltered;
import static org.mariotaku.twidere.util.Utils.openImage;
import static org.mariotaku.twidere.util.Utils.openUserProfile;
private Cursor mCursor;
private CursorIndices mIndices;
public class CursorStatusesAdapter extends BaseCursorAdapter implements IStatusesListAdapter<Cursor>, OnClickListener,
OnOverflowIconClickListener {
public static final String[] CURSOR_COLS = Statuses.COLUMNS;
private final Context mContext;
private final ImageLoaderWrapper mImageLoader;
private final MultiSelectManager mMultiSelectManager;
private final SQLiteDatabase mDatabase;
private final ImageLoadingHandler mImageLoadingHandler;
private MenuButtonClickListener mListener;
private final boolean mPlainList;
private boolean mDisplayImagePreview, mGapDisallowed, mMentionsHighlightDisabled, mFavoritesHighlightDisabled,
mDisplaySensitiveContents, mIndicateMyStatusDisabled, mIsLastItemFiltered, mFiltersEnabled,
mAnimationEnabled;
private boolean mFilterIgnoreUser, mFilterIgnoreSource, mFilterIgnoreTextHtml, mFilterIgnoreTextPlain,
mFilterRetweetedById;
private int mMaxAnimationPosition, mCardHighlightOption;
private ParcelableStatus.CursorIndices mIndices;
private ScaleType mImagePreviewScaleType;
public CursorStatusesAdapter(final Context context) {
this(context, Utils.isCompactCards(context), Utils.isPlainListStyle(context));
}
public CursorStatusesAdapter(final Context context, final boolean compactCards, final boolean plainList) {
super(context, getItemResource(compactCards), null, new String[0], new int[0], 0);
mPlainList = plainList;
mContext = context;
final TwidereApplication application = TwidereApplication.getInstance(context);
mMultiSelectManager = application.getMultiSelectManager();
mImageLoader = application.getImageLoaderWrapper();
mDatabase = application.getSQLiteDatabase();
mImageLoadingHandler = new ImageLoadingHandler();
configBaseCardAdapter(context, this);
setMaxAnimationPosition(-1);
public CursorStatusesAdapter(Context context, boolean compact) {
super(context, compact);
}
@Override
public void bindView(final View view, final Context context, final Cursor cursor) {
final int position = cursor.getPosition();
final StatusListViewHolder holder = (StatusListViewHolder) view.getTag();
public boolean isGapItem(int position) {
final Cursor c = mCursor;
return c != null && c.moveToPosition(position) && c.getInt(mIndices.is_gap) == 1;
}
final boolean isGap = cursor.getShort(mIndices.is_gap) == 1;
final boolean showGap = isGap && !mGapDisallowed && position != getCount() - 1;
@Override
protected void bindStatus(StatusViewHolder holder, int position) {
mCursor.moveToPosition(position);
holder.displayStatus(mCursor, mIndices);
}
holder.setShowAsGap(showGap);
holder.position = position;
holder.setDisplayProfileImage(isDisplayProfileImage());
holder.setCardHighlightOption(mCardHighlightOption);
if (!showGap) {
// Clear images in prder to prevent images in recycled view shown.
final Resources res = mContext.getResources();
final TwidereLinkify linkify = getLinkify();
final boolean showAccountColor = isShowAccountColor();
final long accountId = cursor.getLong(mIndices.account_id);
final long userId = cursor.getLong(mIndices.user_id);
final long timestamp = cursor.getLong(mIndices.status_timestamp);
final long retweetTimestamp = cursor.getLong(mIndices.retweet_timestamp);
final long retweetCount = cursor.getLong(mIndices.retweet_count);
final long retweetedByUserId = cursor.getLong(mIndices.retweeted_by_user_id);
final long inReplyToUserId = cursor.getLong(mIndices.in_reply_to_user_id);
final String retweetedByName = cursor.getString(mIndices.retweeted_by_user_name);
final String retweetedByScreenName = cursor.getString(mIndices.retweeted_by_user_screen_name);
final String text = getLinkHighlightOption() != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE ? cursor
.getString(mIndices.text_html) : cursor.getString(mIndices.text_unescaped);
final String screen_name = cursor.getString(mIndices.user_screen_name);
final String name = cursor.getString(mIndices.user_name);
final String inReplyToName = cursor.getString(mIndices.in_reply_to_user_name);
final String inReplyToScreenName = cursor.getString(mIndices.in_reply_to_user_screen_name);
final ParcelableMedia[] media = ParcelableMedia.fromJSONString(cursor.getString(mIndices.media));
final String firstMedia = media != null && media.length > 0 ? media[0].media_url : null;
// Tweet type (favorite/location/media)
final boolean isFavorite = cursor.getShort(mIndices.is_favorite) == 1;
final boolean hasLocation = !TextUtils.isEmpty(cursor.getString(mIndices.location));
final boolean possiblySensitive = cursor.getInt(mIndices.is_possibly_sensitive) == 1;
final boolean hasMedia = media != null && media.length > 0;
// User type (protected/verified)
final boolean isVerified = cursor.getShort(mIndices.is_verified) == 1;
final boolean isProtected = cursor.getShort(mIndices.is_protected) == 1;
final boolean isRetweet = cursor.getShort(mIndices.is_retweet) == 1;
final boolean isReply = cursor.getLong(mIndices.in_reply_to_status_id) > 0;
final boolean isMention = ParcelableUserMention.hasMention(cursor.getString(mIndices.mentions), accountId);
final boolean isMyStatus = accountId == userId;
holder.setUserColor(getUserColor(mContext, userId));
if (isRetweet) {
holder.setUserColor(getUserColor(mContext, userId), getUserColor(mContext, retweetedByUserId));
} else {
holder.setUserColor(getUserColor(mContext, userId));
}
holder.setHighlightColor(getCardHighlightColor(res, !mMentionsHighlightDisabled && isMention,
!mFavoritesHighlightDisabled && isFavorite, isRetweet));
holder.setAccountColorEnabled(showAccountColor);
if (showAccountColor) {
holder.setAccountColor(getAccountColor(mContext, accountId));
}
holder.setTextSize(getTextSize());
holder.setIsMyStatus(isMyStatus && !mIndicateMyStatusDisabled);
if (getLinkHighlightOption() != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) {
holder.text.setText(Html.fromHtml(text));
linkify.applyAllLinks(holder.text, accountId, possiblySensitive);
holder.text.setMovementMethod(null);
} else {
holder.text.setText(text);
}
holder.setUserType(isVerified, isProtected);
holder.setDisplayNameFirst(isDisplayNameFirst());
holder.setNicknameOnly(isNicknameOnly());
final String nick = getUserNickname(context, userId);
holder.name.setText(TextUtils.isEmpty(nick) ? name : isNicknameOnly() ? nick : context.getString(
R.string.name_with_nickname, name, nick));
holder.screen_name.setText("@" + screen_name);
if (getLinkHighlightOption() != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) {
linkify.applyUserProfileLinkNoHighlight(holder.name, accountId, userId, screen_name);
linkify.applyUserProfileLinkNoHighlight(holder.screen_name, accountId, userId, screen_name);
holder.name.setMovementMethod(null);
holder.screen_name.setMovementMethod(null);
}
holder.time.setTime(retweetTimestamp > 0 ? retweetTimestamp : timestamp);
holder.setStatusType(!mFavoritesHighlightDisabled && isFavorite, hasLocation, hasMedia, possiblySensitive);
holder.setIsReplyRetweet(isReply, isRetweet);
if (isRetweet) {
holder.setRetweetedBy(retweetCount, retweetedByUserId, retweetedByName, retweetedByScreenName);
} else if (isReply) {
holder.setReplyTo(inReplyToUserId, inReplyToName, inReplyToScreenName);
}
if (isDisplayProfileImage()) {
final String profile_image_url = cursor.getString(mIndices.user_profile_image_url);
mImageLoader.displayProfileImage(holder.my_profile_image, profile_image_url);
mImageLoader.displayProfileImage(holder.profile_image, profile_image_url);
holder.profile_image.setTag(position);
holder.my_profile_image.setTag(position);
} else {
mImageLoader.cancelDisplayTask(holder.profile_image);
mImageLoader.cancelDisplayTask(holder.my_profile_image);
holder.profile_image.setVisibility(View.GONE);
holder.my_profile_image.setVisibility(View.GONE);
}
final boolean hasPreview = mDisplayImagePreview && hasMedia;
holder.image_preview_container.setVisibility(hasPreview ? View.VISIBLE : View.GONE);
if (hasPreview && firstMedia != null && media != null) {
if (mImagePreviewScaleType != null) {
holder.image_preview.setScaleType(mImagePreviewScaleType);
}
if (possiblySensitive && !mDisplaySensitiveContents) {
holder.image_preview.setImageDrawable(null);
holder.image_preview.setBackgroundResource(R.drawable.image_preview_nsfw);
holder.image_preview_progress.setVisibility(View.GONE);
mImageLoader.cancelDisplayTask(holder.image_preview);
} else if (!firstMedia.equals(mImageLoadingHandler.getLoadingUri(holder.image_preview))) {
holder.image_preview.setBackgroundResource(0);
mImageLoader.displayPreviewImage(holder.image_preview, firstMedia, mImageLoadingHandler);
}
final int count = media.length;
holder.image_preview_count.setText(res.getQuantityString(R.plurals.N_media, count, count));
holder.image_preview.setTag(position);
} else {
mImageLoader.cancelDisplayTask(holder.image_preview);
}
} else {
mImageLoader.cancelDisplayTask(holder.profile_image);
mImageLoader.cancelDisplayTask(holder.my_profile_image);
mImageLoader.cancelDisplayTask(holder.image_preview);
@Override
public ParcelableStatus getStatus(int position) {
if (hasLoadMoreIndicator() && position == getStatusCount() - 1) return null;
final Cursor c = mCursor;
if (c != null && !c.isClosed() && c.moveToPosition(position)) {
return new ParcelableStatus(c, mIndices);
}
}
@Override
public int findPositionByStatusId(final long status_id) {
final Cursor c = getCursor();
if (c == null || c.isClosed()) return -1;
for (int i = 0, count = c.getCount(); i < count; i++) {
if (c.moveToPosition(i) && c.getLong(mIndices.status_id) == status_id) return i;
}
return -1;
}
@Override
public long getAccountId(final int position) {
final Cursor c = getCursor();
if (c == null || c.isClosed() || !c.moveToPosition(position)) return -1;
return c.getLong(mIndices.account_id);
return null;
}
@Override
public int getStatusCount() {
return super.getCount();
if (mCursor == null) return 0;
return mCursor.getCount();
}
@Override
public int getCount() {
final int count = super.getCount();
return mFiltersEnabled && mIsLastItemFiltered && count > 0 ? count - 1 : count;
public void setData(Cursor data) {
mCursor = data;
mIndices = data != null ? new CursorIndices(data) : null;
notifyDataSetChanged();
}
@Override
public ParcelableStatus getLastStatus() {
final Cursor c = getCursor();
if (c == null || c.isClosed() || !c.moveToLast()) return null;
final long account_id = c.getLong(mIndices.account_id);
final long status_id = c.getLong(mIndices.status_id);
return findStatusInDatabases(mContext, account_id, status_id);
}
@Override
public long getLastStatusId() {
final Cursor c = getCursor();
try {
if (c == null || c.isClosed() || !c.moveToLast()) return -1;
return c.getLong(mIndices.status_id);
} catch (final IllegalStateException e) {
return -1;
}
}
@Override
public Context getContext() {
return mContext;
}
@Override
public ImageLoadingHandler getImageLoadingHandler() {
return mImageLoadingHandler;
}
@Override
public ParcelableStatus getStatus(final int position) {
final Cursor c = getCursor();
if (c == null || c.isClosed() || !c.moveToPosition(position)) return null;
return new ParcelableStatus(c, mIndices);
}
@Override
public long getStatusId(final int position) {
final Cursor c = getCursor();
if (c == null || c.isClosed() || !c.moveToPosition(position)) return -1;
return c.getLong(mIndices.status_id);
}
@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();
// animate the item
if (tag instanceof StatusListViewHolder && position > mMaxAnimationPosition) {
if (mAnimationEnabled) {
view.startAnimation(((StatusListViewHolder) tag).item_animation);
}
mMaxAnimationPosition = position;
}
return view;
}
@Override
public boolean isLastItemFiltered() {
return mFiltersEnabled && mIsLastItemFiltered;
}
@Override
public View newView(final Context context, final Cursor cursor, final ViewGroup parent) {
final View view = super.newView(context, cursor, parent);
final Object tag = view.getTag();
if (!(tag instanceof StatusListViewHolder)) {
final StatusListViewHolder holder = new StatusListViewHolder(view);
holder.profile_image.setOnClickListener(this);
holder.my_profile_image.setOnClickListener(this);
holder.image_preview.setOnClickListener(this);
holder.content.setOnOverflowIconClickListener(this);
if (mPlainList) {
((View) holder.content).setPadding(0, 0, 0, 0);
holder.content.setItemBackground(null);
}
view.setTag(holder);
}
return view;
}
@Override
public void onClick(final View view) {
if (mMultiSelectManager.isActive()) return;
final Object tag = view.getTag();
final int position = tag instanceof Integer ? (Integer) tag : -1;
if (position == -1) return;
switch (view.getId()) {
case R.id.image_preview: {
final ParcelableStatus status = getStatus(position);
if (status == null || status.first_media == null) return;
openImage(mContext, status.account_id, status.first_media, status.is_possibly_sensitive);
break;
}
case R.id.my_profile_image:
case R.id.profile_image: {
final ParcelableStatus status = getStatus(position);
if (status == null) return;
final Activity activity = (Activity) getContext();
final Bundle options = Utils.makeSceneTransitionOption(activity,
new Pair<>(view, UserFragment.TRANSITION_NAME_PROFILE_IMAGE));
openUserProfile(mContext, status.account_id, status.user_id,
status.user_screen_name, options);
break;
}
}
}
@Override
public void onOverflowIconClick(final View view) {
if (mMultiSelectManager.isActive()) return;
final Object tag = view.getTag();
if (tag instanceof StatusListViewHolder) {
final StatusListViewHolder holder = (StatusListViewHolder) tag;
final int position = holder.position;
if (position == -1 || mListener == null) return;
mListener.onMenuButtonClick(view, position, getItemId(position));
}
}
@Override
public void setAnimationEnabled(final boolean anim) {
mAnimationEnabled = anim;
}
@Override
public void setCardHighlightOption(final String option) {
mCardHighlightOption = getCardHighlightOptionInt(option);
}
@Override
public void setData(final Cursor data) {
swapCursor(data);
}
@Override
public void setDisplayImagePreview(final boolean display) {
mDisplayImagePreview = display;
}
@Override
public void setDisplaySensitiveContents(final boolean display) {
mDisplaySensitiveContents = display;
}
@Override
public void setFavoritesHightlightDisabled(final boolean disable) {
mFavoritesHighlightDisabled = disable;
}
@Override
public void setFiltersEnabled(final boolean enabled) {
if (mFiltersEnabled == enabled) return;
mFiltersEnabled = enabled;
rebuildFilterInfo(getCursor(), mIndices);
}
@Override
public void setGapDisallowed(final boolean disallowed) {
mGapDisallowed = disallowed;
}
@Override
public void setHighlightKeyword(final String... keywords) {
// TODO Auto-generated method stub
public void onGapClick(StatusViewHolder holder, int position) {
}
@Override
public void setIgnoredFilterFields(final boolean user, final boolean textPlain, final boolean textHtml,
final boolean source, final boolean retweetedById) {
mFilterIgnoreTextPlain = textPlain;
mFilterIgnoreTextHtml = textHtml;
mFilterIgnoreUser = user;
mFilterIgnoreSource = source;
mFilterRetweetedById = retweetedById;
rebuildFilterInfo(getCursor(), mIndices);
}
@Override
public void setImagePreviewScaleType(final String scaleTypeString) {
final ScaleType scaleType = ScaleType.valueOf(scaleTypeString.toUpperCase(Locale.US));
mImagePreviewScaleType = scaleType;
}
@Override
public void setIndicateMyStatusDisabled(final boolean disable) {
mIndicateMyStatusDisabled = disable;
}
@Override
public void setMaxAnimationPosition(final int position) {
mMaxAnimationPosition = position;
}
@Override
public void setMentionsHightlightDisabled(final boolean disable) {
mMentionsHighlightDisabled = disable;
}
@Override
public void setMenuButtonClickListener(final MenuButtonClickListener listener) {
mListener = listener;
}
@Override
public Cursor swapCursor(final Cursor cursor) {
mIndices = cursor != null ? new ParcelableStatus.CursorIndices(cursor) : null;
rebuildFilterInfo(cursor, mIndices);
return super.swapCursor(cursor);
}
private void rebuildFilterInfo(final Cursor c, final ParcelableStatus.CursorIndices i) {
if (i != null && c != null && moveCursorToLast(c)) {
final long userId = mFilterIgnoreUser ? -1 : c.getLong(mIndices.user_id);
final String textPlain = mFilterIgnoreTextPlain ? null : c.getString(mIndices.text_plain);
final String textHtml = mFilterIgnoreTextHtml ? null : c.getString(mIndices.text_html);
final String source = mFilterIgnoreSource ? null : c.getString(mIndices.source);
final long retweetedById = mFilterRetweetedById ? -1 : c.getLong(mIndices.retweeted_by_user_id);
mIsLastItemFiltered = isFiltered(mDatabase, userId, textPlain, textHtml, source, retweetedById);
} else {
mIsLastItemFiltered = false;
}
}
private static int getItemResource(final boolean compactCards) {
return compactCards ? R.layout.card_item_status_compact : R.layout.card_item_status;
}
private static boolean moveCursorToLast(final Cursor c) {
if (c == null || c.isClosed()) return false;
try {
return c.moveToNext();
} catch (final Exception e) {
return false;
}
public Cursor getData() {
return mCursor;
}
}

View File

@ -0,0 +1,370 @@
/*
* 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;
import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v4.util.Pair;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView.ScaleType;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.fragment.support.UserFragment;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.provider.TweetStore.Statuses;
import org.mariotaku.twidere.util.ImageLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.MultiSelectManager;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.view.holder.StatusViewHolder;
import org.mariotaku.twidere.view.iface.ICardItemView.OnOverflowIconClickListener;
import java.util.Locale;
import static org.mariotaku.twidere.util.Utils.configBaseCardAdapter;
import static org.mariotaku.twidere.util.Utils.findStatusInDatabases;
import static org.mariotaku.twidere.util.Utils.getCardHighlightOptionInt;
import static org.mariotaku.twidere.util.Utils.isFiltered;
import static org.mariotaku.twidere.util.Utils.openImage;
import static org.mariotaku.twidere.util.Utils.openUserProfile;
public class CursorStatusesListAdapter extends BaseCursorAdapter implements IStatusesListAdapter<Cursor>, OnClickListener,
OnOverflowIconClickListener {
public static final String[] CURSOR_COLS = Statuses.COLUMNS;
private final Context mContext;
private final ImageLoaderWrapper mImageLoader;
private final MultiSelectManager mMultiSelectManager;
private final SQLiteDatabase mDatabase;
private final ImageLoadingHandler mImageLoadingHandler;
private MenuButtonClickListener mListener;
private boolean mDisplayImagePreview, mGapDisallowed, mMentionsHighlightDisabled, mFavoritesHighlightDisabled,
mDisplaySensitiveContents, mIndicateMyStatusDisabled, mIsLastItemFiltered, mFiltersEnabled,
mAnimationEnabled;
private boolean mFilterIgnoreUser, mFilterIgnoreSource, mFilterIgnoreTextHtml, mFilterIgnoreTextPlain,
mFilterRetweetedById;
private int mMaxAnimationPosition, mCardHighlightOption;
private ParcelableStatus.CursorIndices mIndices;
private ScaleType mImagePreviewScaleType;
public CursorStatusesListAdapter(final Context context) {
this(context, Utils.isCompactCards(context));
}
public CursorStatusesListAdapter(final Context context, final boolean compactCards) {
super(context, getItemResource(compactCards), null, new String[0], new int[0], 0);
mContext = context;
final TwidereApplication application = TwidereApplication.getInstance(context);
mMultiSelectManager = application.getMultiSelectManager();
mImageLoader = application.getImageLoaderWrapper();
mDatabase = application.getSQLiteDatabase();
mImageLoadingHandler = new ImageLoadingHandler();
configBaseCardAdapter(context, this);
setMaxAnimationPosition(-1);
}
@Override
public void bindView(final View view, final Context context, final Cursor cursor) {
final StatusViewHolder holder = (StatusViewHolder) view.getTag();
holder.displayStatus(cursor, mIndices);
}
@Override
public int findPositionByStatusId(final long status_id) {
final Cursor c = getCursor();
if (c == null || c.isClosed()) return -1;
for (int i = 0, count = c.getCount(); i < count; i++) {
if (c.moveToPosition(i) && c.getLong(mIndices.status_id) == status_id) return i;
}
return -1;
}
@Override
public long getAccountId(final int position) {
final Cursor c = getCursor();
if (c == null || c.isClosed() || !c.moveToPosition(position)) return -1;
return c.getLong(mIndices.account_id);
}
@Override
public int getStatusCount() {
return super.getCount();
}
@Override
public void onItemMenuClick(StatusViewHolder holder, int position) {
}
@Override
public void onStatusClick(StatusViewHolder holder, int position) {
}
@Override
public void onUserProfileClick(StatusViewHolder holder, int position) {
}
@Override
public int getCount() {
final int count = super.getCount();
return mFiltersEnabled && mIsLastItemFiltered && count > 0 ? count - 1 : count;
}
@Override
public ParcelableStatus getLastStatus() {
final Cursor c = getCursor();
if (c == null || c.isClosed() || !c.moveToLast()) return null;
final long account_id = c.getLong(mIndices.account_id);
final long status_id = c.getLong(mIndices.status_id);
return findStatusInDatabases(mContext, account_id, status_id);
}
@Override
public long getLastStatusId() {
final Cursor c = getCursor();
try {
if (c == null || c.isClosed() || !c.moveToLast()) return -1;
return c.getLong(mIndices.status_id);
} catch (final IllegalStateException e) {
return -1;
}
}
@Override
public Context getContext() {
return mContext;
}
@Override
public ImageLoadingHandler getImageLoadingHandler() {
return mImageLoadingHandler;
}
@Override
public ParcelableStatus getStatus(final int position) {
final Cursor c = getCursor();
if (c == null || c.isClosed() || !c.moveToPosition(position)) return null;
return new ParcelableStatus(c, mIndices);
}
@Override
public long getStatusId(final int position) {
final Cursor c = getCursor();
if (c == null || c.isClosed() || !c.moveToPosition(position)) return -1;
return c.getLong(mIndices.status_id);
}
@Override
public boolean isGapItem(int position) {
return false;
}
@Override
public boolean isLastItemFiltered() {
return mFiltersEnabled && mIsLastItemFiltered;
}
@Override
public View newView(final Context context, final Cursor cursor, final ViewGroup parent) {
final View view = super.newView(context, cursor, parent);
final Object tag = view.getTag();
if (!(tag instanceof StatusViewHolder)) {
final StatusViewHolder holder = new StatusViewHolder(this, view);
view.setTag(holder);
}
return view;
}
@Override
public void onClick(final View view) {
if (mMultiSelectManager.isActive()) return;
final Object tag = view.getTag();
final int position = tag instanceof Integer ? (Integer) tag : -1;
if (position == -1) return;
switch (view.getId()) {
case R.id.image_preview: {
final ParcelableStatus status = getStatus(position);
if (status == null || status.first_media == null) return;
openImage(mContext, status.account_id, status.first_media, status.is_possibly_sensitive);
break;
}
case R.id.my_profile_image:
case R.id.profile_image: {
final ParcelableStatus status = getStatus(position);
if (status == null) return;
final Activity activity = (Activity) getContext();
final Bundle options = Utils.makeSceneTransitionOption(activity,
new Pair<>(view, UserFragment.TRANSITION_NAME_PROFILE_IMAGE));
openUserProfile(mContext, status.account_id, status.user_id,
status.user_screen_name, options);
break;
}
}
}
@Override
public void onOverflowIconClick(final View view) {
if (mMultiSelectManager.isActive()) return;
final Object tag = view.getTag();
if (tag instanceof StatusViewHolder) {
final StatusViewHolder holder = (StatusViewHolder) tag;
final int position = holder.getPosition();
if (position == -1 || mListener == null) return;
mListener.onMenuButtonClick(view, position, getItemId(position));
}
}
@Override
public void setAnimationEnabled(final boolean anim) {
mAnimationEnabled = anim;
}
@Override
public void setCardHighlightOption(final String option) {
mCardHighlightOption = getCardHighlightOptionInt(option);
}
@Override
public void setData(final Cursor data) {
swapCursor(data);
}
@Override
public void setDisplayImagePreview(final boolean display) {
mDisplayImagePreview = display;
}
@Override
public void setDisplaySensitiveContents(final boolean display) {
mDisplaySensitiveContents = display;
}
@Override
public void setFavoritesHightlightDisabled(final boolean disable) {
mFavoritesHighlightDisabled = disable;
}
@Override
public void setFiltersEnabled(final boolean enabled) {
if (mFiltersEnabled == enabled) return;
mFiltersEnabled = enabled;
rebuildFilterInfo(getCursor(), mIndices);
}
@Override
public void setGapDisallowed(final boolean disallowed) {
mGapDisallowed = disallowed;
}
@Override
public void setHighlightKeyword(final String... keywords) {
// TODO Auto-generated method stub
}
@Override
public void setIgnoredFilterFields(final boolean user, final boolean textPlain, final boolean textHtml,
final boolean source, final boolean retweetedById) {
mFilterIgnoreTextPlain = textPlain;
mFilterIgnoreTextHtml = textHtml;
mFilterIgnoreUser = user;
mFilterIgnoreSource = source;
mFilterRetweetedById = retweetedById;
rebuildFilterInfo(getCursor(), mIndices);
}
@Override
public void setImagePreviewScaleType(final String scaleTypeString) {
final ScaleType scaleType = ScaleType.valueOf(scaleTypeString.toUpperCase(Locale.US));
mImagePreviewScaleType = scaleType;
}
@Override
public void setIndicateMyStatusDisabled(final boolean disable) {
mIndicateMyStatusDisabled = disable;
}
@Override
public void setMaxAnimationPosition(final int position) {
mMaxAnimationPosition = position;
}
@Override
public void setMentionsHightlightDisabled(final boolean disable) {
mMentionsHighlightDisabled = disable;
}
@Override
public void setMenuButtonClickListener(final MenuButtonClickListener listener) {
mListener = listener;
}
@Override
public Cursor swapCursor(final Cursor cursor) {
mIndices = cursor != null ? new ParcelableStatus.CursorIndices(cursor) : null;
rebuildFilterInfo(cursor, mIndices);
return super.swapCursor(cursor);
}
private void rebuildFilterInfo(final Cursor c, final ParcelableStatus.CursorIndices i) {
if (i != null && c != null && moveCursorToLast(c)) {
final long userId = mFilterIgnoreUser ? -1 : c.getLong(mIndices.user_id);
final String textPlain = mFilterIgnoreTextPlain ? null : c.getString(mIndices.text_plain);
final String textHtml = mFilterIgnoreTextHtml ? null : c.getString(mIndices.text_html);
final String source = mFilterIgnoreSource ? null : c.getString(mIndices.source);
final long retweetedById = mFilterRetweetedById ? -1 : c.getLong(mIndices.retweeted_by_user_id);
mIsLastItemFiltered = isFiltered(mDatabase, userId, textPlain, textHtml, source, retweetedById);
} else {
mIsLastItemFiltered = false;
}
}
private static int getItemResource(final boolean compactCards) {
return compactCards ? R.layout.card_item_list_status_compat : R.layout.card_item_list_status;
}
private static boolean moveCursorToLast(final Cursor c) {
if (c == null || c.isClosed()) return false;
try {
return c.moveToNext();
} catch (final Exception e) {
return false;
}
}
@Override
public void onGapClick(StatusViewHolder holder, int position) {
}
}

View File

@ -58,16 +58,12 @@ public class DirectMessageConversationEntriesAdapter extends BaseCursorAdapter i
private boolean mAnimationEnabled;
private int mMaxAnimationPosition;
private final boolean mPlainList;
public DirectMessageConversationEntriesAdapter(final Context context) {
this(context, Utils.isCompactCards(context), Utils.isPlainListStyle(context));
this(context, Utils.isCompactCards(context));
}
public DirectMessageConversationEntriesAdapter(final Context context, final boolean compactCards,
final boolean plainList) {
public DirectMessageConversationEntriesAdapter(final Context context, final boolean compactCards) {
super(context, getItemResource(compactCards), null, new String[0], new int[0], 0);
mPlainList = plainList;
final TwidereApplication app = TwidereApplication.getInstance(context);
mMultiSelectManager = app.getMultiSelectManager();
mImageLoader = app.getImageLoaderWrapper();
@ -148,10 +144,6 @@ public class DirectMessageConversationEntriesAdapter extends BaseCursorAdapter i
if (!(tag instanceof DirectMessageEntryViewHolder)) {
final DirectMessageEntryViewHolder holder = new DirectMessageEntryViewHolder(view);
holder.profile_image.setOnClickListener(this);
if (mPlainList) {
((View) holder.content).setPadding(0, 0, 0, 0);
holder.content.setItemBackground(null);
}
view.setTag(holder);
}
return view;

View File

@ -50,8 +50,8 @@ public class ParcelableActivitiesAboutMeAdapter extends BaseParcelableActivities
private boolean mDisplayImagePreview;
private boolean mDisplaySensitiveContents;
public ParcelableActivitiesAboutMeAdapter(final Context context, final boolean compactCards, final boolean plainList) {
super(context, compactCards, plainList);
public ParcelableActivitiesAboutMeAdapter(final Context context, final boolean compactCards) {
super(context, compactCards);
mImageLoadingHandler = new ImageLoadingHandler();
}

View File

@ -34,140 +34,139 @@ import org.mariotaku.twidere.view.holder.ActivityListViewHolder;
public class ParcelableActivitiesByFriendsAdapter extends BaseParcelableActivitiesAdapter {
public ParcelableActivitiesByFriendsAdapter(final Context context, final boolean compactCards,
final boolean plainList) {
super(context, compactCards, plainList);
}
public ParcelableActivitiesByFriendsAdapter(final Context context, final boolean compactCards) {
super(context, compactCards);
}
@Override
public void bindView(final int position, final ActivityListViewHolder holder, final ParcelableActivity item) {
if (item == null) return;
final ParcelableUser[] sources = item.sources;
final ParcelableStatus[] targetStatuses = item.target_statuses;
final ParcelableUser[] targetUsers = item.target_users;
final ParcelableStatus[] target_object_statuses = item.target_object_statuses;
final ParcelableUserList[] targetUserLists = item.target_user_lists;
final ParcelableUserList[] target_object_user_lists = item.target_object_user_lists;
final int sourcesLength = sources != null ? sources.length : 0;
final int targetStatusesLength = targetStatuses != null ? targetStatuses.length : 0;
final int target_users_length = targetUsers != null ? targetUsers.length : 0;
final int target_object_user_lists_length = target_object_user_lists != null ? target_object_user_lists.length
: 0;
final int target_user_lists_length = targetUserLists != null ? targetUserLists.length : 0;
final int action = item.action;
final Context context = getContext();
@Override
public void bindView(final int position, final ActivityListViewHolder holder, final ParcelableActivity item) {
if (item == null) return;
final ParcelableUser[] sources = item.sources;
final ParcelableStatus[] targetStatuses = item.target_statuses;
final ParcelableUser[] targetUsers = item.target_users;
final ParcelableStatus[] target_object_statuses = item.target_object_statuses;
final ParcelableUserList[] targetUserLists = item.target_user_lists;
final ParcelableUserList[] target_object_user_lists = item.target_object_user_lists;
final int sourcesLength = sources != null ? sources.length : 0;
final int targetStatusesLength = targetStatuses != null ? targetStatuses.length : 0;
final int target_users_length = targetUsers != null ? targetUsers.length : 0;
final int target_object_user_lists_length = target_object_user_lists != null ? target_object_user_lists.length
: 0;
final int target_user_lists_length = targetUserLists != null ? targetUserLists.length : 0;
final int action = item.action;
final Context context = getContext();
final TwidereLinkify linkify = getLinkify();
final int highlightOption = getLinkHighlightOption();
final TwidereLinkify linkify = getLinkify();
final int highlightOption = getLinkHighlightOption();
holder.name.setSingleLine(false);
holder.screen_name.setVisibility(View.GONE);
holder.reply_retweet_status.setVisibility(View.GONE);
if (holder.divider != null) {
holder.divider.setVisibility(View.VISIBLE);
}
if (sources != null && sources.length != 0) {
final ParcelableUser firstSource = sources[0];
final String firstSourceName = getName(firstSource);
switch (action) {
case ParcelableActivity.ACTION_FAVORITE: {
if (targetStatuses == null || targetStatuses.length == 0) return;
final ParcelableStatus status = targetStatuses[0];
if (targetStatusesLength == 1) {
holder.text.setVisibility(View.VISIBLE);
if (highlightOption != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) {
holder.text.setText(Html.fromHtml(status.text_html));
linkify.applyAllLinks(holder.text, status.account_id, status.is_possibly_sensitive);
holder.text.setMovementMethod(null);
} else {
holder.text.setText(status.text_unescaped);
}
holder.name.setText(context.getString(R.string.activity_by_friends_favorite, firstSourceName,
getName(status)));
} else {
holder.text.setVisibility(View.GONE);
holder.name.setText(context.getString(R.string.activity_by_friends_favorite_multi,
firstSourceName, getName(status), targetStatusesLength - 1));
}
displayProfileImage(holder.profile_image, firstSource);
displayActivityUserProfileImages(holder, targetStatuses);
break;
}
case ParcelableActivity.ACTION_FOLLOW: {
holder.text.setVisibility(View.GONE);
if (targetUsers == null || targetUsers.length == 0) return;
if (targetUsers.length == 1) {
holder.name.setText(context.getString(R.string.activity_by_friends_follow, firstSourceName,
getName(targetUsers[0])));
} else {
holder.name.setText(context.getString(R.string.activity_by_friends_follow_multi,
firstSourceName, getName(targetUsers[0]), target_users_length - 1));
}
displayProfileImage(holder.profile_image, firstSource);
displayActivityUserProfileImages(holder, targetUsers);
break;
}
case ParcelableActivity.ACTION_RETWEET: {
holder.text.setVisibility(View.VISIBLE);
if (target_object_statuses != null && target_object_statuses.length > 0) {
final ParcelableStatus status = target_object_statuses[0];
if (highlightOption != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) {
holder.text.setText(Html.fromHtml(status.text_html));
linkify.applyAllLinks(holder.text, status.account_id, status.is_possibly_sensitive);
holder.text.setMovementMethod(null);
} else {
holder.text.setText(status.text_unescaped);
}
}
if (sourcesLength == 1) {
holder.name.setText(context.getString(R.string.activity_by_friends_retweet, firstSourceName,
getName(targetStatuses[0])));
} else {
holder.name.setText(context.getString(R.string.activity_about_me_retweet_multi,
firstSourceName, sourcesLength - 1));
}
displayActivityUserProfileImages(holder, sources);
break;
}
case ParcelableActivity.ACTION_LIST_MEMBER_ADDED: {
holder.text.setVisibility(View.GONE);
if (target_object_user_lists_length == 1) {
holder.name.setText(context.getString(R.string.activity_by_friends_list_member_added,
firstSourceName, getName(targetUsers[0])));
} else {
holder.name.setText(context.getString(R.string.activity_about_me_list_member_added_multi,
firstSourceName, sourcesLength - 1));
}
displayProfileImage(holder.profile_image, firstSource);
displayActivityUserProfileImages(holder, targetUsers);
break;
}
case ParcelableActivity.ACTION_LIST_CREATED: {
if (target_user_lists_length == 0) return;
holder.activity_profile_images_container.setVisibility(View.GONE);
final ParcelableUserList userList = targetUserLists[0];
if (target_user_lists_length == 1) {
if (!TextUtils.isEmpty(userList.description)) {
holder.text.setVisibility(View.VISIBLE);
holder.text.setText(userList.description);
} else {
if (holder.divider != null) {
holder.divider.setVisibility(View.GONE);
}
holder.text.setVisibility(View.GONE);
}
holder.name.setText(context.getString(R.string.activity_by_friends_list_created,
firstSourceName, userList.name));
} else {
holder.text.setVisibility(View.GONE);
holder.name.setText(context.getString(R.string.activity_by_friends_list_created_multi,
firstSourceName, userList.name, target_user_lists_length - 1));
}
displayProfileImage(holder.profile_image, firstSource);
break;
}
}
}
}
holder.name.setSingleLine(false);
holder.screen_name.setVisibility(View.GONE);
holder.reply_retweet_status.setVisibility(View.GONE);
if (holder.divider != null) {
holder.divider.setVisibility(View.VISIBLE);
}
if (sources != null && sources.length != 0) {
final ParcelableUser firstSource = sources[0];
final String firstSourceName = getName(firstSource);
switch (action) {
case ParcelableActivity.ACTION_FAVORITE: {
if (targetStatuses == null || targetStatuses.length == 0) return;
final ParcelableStatus status = targetStatuses[0];
if (targetStatusesLength == 1) {
holder.text.setVisibility(View.VISIBLE);
if (highlightOption != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) {
holder.text.setText(Html.fromHtml(status.text_html));
linkify.applyAllLinks(holder.text, status.account_id, status.is_possibly_sensitive);
holder.text.setMovementMethod(null);
} else {
holder.text.setText(status.text_unescaped);
}
holder.name.setText(context.getString(R.string.activity_by_friends_favorite, firstSourceName,
getName(status)));
} else {
holder.text.setVisibility(View.GONE);
holder.name.setText(context.getString(R.string.activity_by_friends_favorite_multi,
firstSourceName, getName(status), targetStatusesLength - 1));
}
displayProfileImage(holder.profile_image, firstSource);
displayActivityUserProfileImages(holder, targetStatuses);
break;
}
case ParcelableActivity.ACTION_FOLLOW: {
holder.text.setVisibility(View.GONE);
if (targetUsers == null || targetUsers.length == 0) return;
if (targetUsers.length == 1) {
holder.name.setText(context.getString(R.string.activity_by_friends_follow, firstSourceName,
getName(targetUsers[0])));
} else {
holder.name.setText(context.getString(R.string.activity_by_friends_follow_multi,
firstSourceName, getName(targetUsers[0]), target_users_length - 1));
}
displayProfileImage(holder.profile_image, firstSource);
displayActivityUserProfileImages(holder, targetUsers);
break;
}
case ParcelableActivity.ACTION_RETWEET: {
holder.text.setVisibility(View.VISIBLE);
if (target_object_statuses != null && target_object_statuses.length > 0) {
final ParcelableStatus status = target_object_statuses[0];
if (highlightOption != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) {
holder.text.setText(Html.fromHtml(status.text_html));
linkify.applyAllLinks(holder.text, status.account_id, status.is_possibly_sensitive);
holder.text.setMovementMethod(null);
} else {
holder.text.setText(status.text_unescaped);
}
}
if (sourcesLength == 1) {
holder.name.setText(context.getString(R.string.activity_by_friends_retweet, firstSourceName,
getName(targetStatuses[0])));
} else {
holder.name.setText(context.getString(R.string.activity_about_me_retweet_multi,
firstSourceName, sourcesLength - 1));
}
displayActivityUserProfileImages(holder, sources);
break;
}
case ParcelableActivity.ACTION_LIST_MEMBER_ADDED: {
holder.text.setVisibility(View.GONE);
if (target_object_user_lists_length == 1) {
holder.name.setText(context.getString(R.string.activity_by_friends_list_member_added,
firstSourceName, getName(targetUsers[0])));
} else {
holder.name.setText(context.getString(R.string.activity_about_me_list_member_added_multi,
firstSourceName, sourcesLength - 1));
}
displayProfileImage(holder.profile_image, firstSource);
displayActivityUserProfileImages(holder, targetUsers);
break;
}
case ParcelableActivity.ACTION_LIST_CREATED: {
if (target_user_lists_length == 0) return;
holder.activity_profile_images_container.setVisibility(View.GONE);
final ParcelableUserList userList = targetUserLists[0];
if (target_user_lists_length == 1) {
if (!TextUtils.isEmpty(userList.description)) {
holder.text.setVisibility(View.VISIBLE);
holder.text.setText(userList.description);
} else {
if (holder.divider != null) {
holder.divider.setVisibility(View.GONE);
}
holder.text.setVisibility(View.GONE);
}
holder.name.setText(context.getString(R.string.activity_by_friends_list_created,
firstSourceName, userList.name));
} else {
holder.text.setVisibility(View.GONE);
holder.name.setText(context.getString(R.string.activity_by_friends_list_created_multi,
firstSourceName, userList.name, target_user_lists_length - 1));
}
displayProfileImage(holder.profile_image, firstSource);
break;
}
}
}
}
}

View File

@ -10,7 +10,7 @@ import java.util.List;
/**
* Created by mariotaku on 14/11/19.
*/
public class ParcelableStatusesAdapter extends AbsStatusesAdapter {
public class ParcelableStatusesAdapter extends AbsStatusesAdapter<List<ParcelableStatus>> {
private List<ParcelableStatus> mData;
@ -18,6 +18,16 @@ public class ParcelableStatusesAdapter extends AbsStatusesAdapter {
super(context, compact);
}
@Override
public boolean isGapItem(int position) {
return getStatus(position).is_gap;
}
@Override
public void onGapClick(StatusViewHolder holder, int position) {
}
@Override
protected void bindStatus(StatusViewHolder holder, int position) {
holder.displayStatus(getStatus(position));
@ -43,4 +53,5 @@ public class ParcelableStatusesAdapter extends AbsStatusesAdapter {
public List<ParcelableStatus> getData() {
return mData;
}
}

View File

@ -21,10 +21,7 @@ package org.mariotaku.twidere.adapter;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.database.sqlite.SQLiteDatabase;
import android.text.Html;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
@ -34,24 +31,17 @@ import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableUserMention;
import org.mariotaku.twidere.util.ImageLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.MultiSelectManager;
import org.mariotaku.twidere.util.TwidereLinkify;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.view.holder.StatusListViewHolder;
import org.mariotaku.twidere.view.holder.StatusViewHolder;
import org.mariotaku.twidere.view.iface.ICardItemView.OnOverflowIconClickListener;
import java.util.List;
import java.util.Locale;
import static org.mariotaku.twidere.model.ParcelableLocation.isValidLocation;
import static org.mariotaku.twidere.util.UserColorNicknameUtils.getUserColor;
import static org.mariotaku.twidere.util.UserColorNicknameUtils.getUserNickname;
import static org.mariotaku.twidere.util.Utils.configBaseCardAdapter;
import static org.mariotaku.twidere.util.Utils.getAccountColor;
import static org.mariotaku.twidere.util.Utils.getCardHighlightColor;
import static org.mariotaku.twidere.util.Utils.getCardHighlightOptionInt;
import static org.mariotaku.twidere.util.Utils.isFiltered;
import static org.mariotaku.twidere.util.Utils.openImage;
@ -67,7 +57,6 @@ public class ParcelableStatusesListAdapter extends BaseArrayAdapter<ParcelableSt
private MenuButtonClickListener mListener;
private final boolean mPlainList;
private boolean mDisplayImagePreview, mGapDisallowed, mMentionsHighlightDisabled, mFavoritesHighlightDisabled,
mDisplaySensitiveContents, mIndicateMyStatusDisabled, mIsLastItemFiltered, mFiltersEnabled,
@ -79,12 +68,11 @@ public class ParcelableStatusesListAdapter extends BaseArrayAdapter<ParcelableSt
private String[] mHighlightKeywords;
public ParcelableStatusesListAdapter(final Context context) {
this(context, Utils.isCompactCards(context), Utils.isPlainListStyle(context));
this(context, Utils.isCompactCards(context));
}
public ParcelableStatusesListAdapter(final Context context, final boolean compactCards, final boolean plainList) {
public ParcelableStatusesListAdapter(final Context context, final boolean compactCards) {
super(context, getItemResource(compactCards));
mPlainList = plainList;
mContext = context;
final TwidereApplication app = TwidereApplication.getInstance(context);
mMultiSelectManager = app.getMultiSelectManager();
@ -116,6 +104,21 @@ public class ParcelableStatusesListAdapter extends BaseArrayAdapter<ParcelableSt
return super.getCount();
}
@Override
public void onItemMenuClick(StatusViewHolder holder, int position) {
}
@Override
public void onStatusClick(StatusViewHolder holder, int position) {
}
@Override
public void onUserProfileClick(StatusViewHolder holder, int position) {
}
@Override
public int getCount() {
final int count = super.getCount();
@ -163,143 +166,28 @@ public class ParcelableStatusesListAdapter extends BaseArrayAdapter<ParcelableSt
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 StatusListViewHolder holder;
final Resources res = mContext.getResources();
if (tag instanceof StatusListViewHolder) {
holder = (StatusListViewHolder) tag;
final StatusViewHolder holder;
if (tag instanceof StatusViewHolder) {
holder = (StatusViewHolder) tag;
} else {
holder = new StatusListViewHolder(view);
holder.profile_image.setOnClickListener(this);
holder.my_profile_image.setOnClickListener(this);
holder.image_preview.setOnClickListener(this);
holder.content.setOnOverflowIconClickListener(this);
if (mPlainList) {
((View) holder.content).setPadding(0, 0, 0, 0);
holder.content.setItemBackground(null);
}
holder = new StatusViewHolder(this, view);
view.setTag(holder);
}
final ParcelableStatus status = getItem(position);
final boolean showGap = status.is_gap && !mGapDisallowed && position != getCount() - 1;
holder.position = position;
holder.setShowAsGap(showGap);
holder.setDisplayProfileImage(isDisplayProfileImage());
holder.setCardHighlightOption(mCardHighlightOption);
final ImageLoaderWrapper loader = getImageLoader();
if (!showGap) {
final TwidereLinkify linkify = getLinkify();
final int highlightOption = getLinkHighlightOption();
final boolean mShowAccountColor = isShowAccountColor();
holder.setAccountColorEnabled(mShowAccountColor);
if (highlightOption != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) {
holder.text.setText(Utils.getKeywordBoldedText(Html.fromHtml(status.text_html), mHighlightKeywords));
linkify.applyAllLinks(holder.text, status.account_id, status.is_possibly_sensitive);
holder.text.setMovementMethod(null);
} else {
if (mHighlightKeywords == null || mHighlightKeywords.length == 0) {
holder.text.setText(status.text_unescaped);
} else {
holder.text.setText(Utils.getKeywordBoldedText(status.text_unescaped, mHighlightKeywords));
}
}
if (mShowAccountColor) {
holder.setAccountColor(getAccountColor(mContext, status.account_id));
}
final boolean isMention = ParcelableUserMention.hasMention(status.mentions, status.account_id);
final boolean isMyStatus = status.account_id == status.user_id;
final boolean hasMedia = status.first_media != null;
if (status.is_retweet) {
holder.setUserColor(getUserColor(mContext, status.user_id),
getUserColor(mContext, status.retweeted_by_id));
} else {
holder.setUserColor(getUserColor(mContext, status.user_id));
}
holder.setHighlightColor(getCardHighlightColor(res,
!mMentionsHighlightDisabled && isMention,
!mFavoritesHighlightDisabled && status.is_favorite, status.is_retweet));
holder.setTextSize(getTextSize());
holder.setIsMyStatus(isMyStatus && !mIndicateMyStatusDisabled);
holder.setUserType(status.user_is_verified, status.user_is_protected);
holder.setDisplayNameFirst(isDisplayNameFirst());
holder.setNicknameOnly(isNicknameOnly());
final String nick = getUserNickname(mContext, status.user_id);
holder.name.setText(TextUtils.isEmpty(nick) ? status.user_name : isNicknameOnly() ? nick : mContext
.getString(R.string.name_with_nickname, status.user_name, nick));
holder.screen_name.setText("@" + status.user_screen_name);
if (highlightOption != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) {
linkify.applyUserProfileLinkNoHighlight(holder.name, status.account_id, status.user_id,
status.user_screen_name);
linkify.applyUserProfileLinkNoHighlight(holder.screen_name, status.account_id, status.user_id,
status.user_screen_name);
holder.name.setMovementMethod(null);
holder.screen_name.setMovementMethod(null);
}
holder.time.setTime(status.retweet_timestamp > 0 ? status.retweet_timestamp : status.timestamp);
holder.setStatusType(!mFavoritesHighlightDisabled && status.is_favorite, isValidLocation(status.location),
hasMedia, status.is_possibly_sensitive);
holder.setIsReplyRetweet(status.in_reply_to_status_id > 0, status.is_retweet);
if (status.is_retweet) {
holder.setRetweetedBy(status.retweet_count, status.retweeted_by_id, status.retweeted_by_name,
status.retweeted_by_screen_name);
} else if (status.in_reply_to_status_id > 0) {
holder.setReplyTo(status.in_reply_to_user_id, status.in_reply_to_name, status.in_reply_to_screen_name);
}
if (isDisplayProfileImage()) {
loader.displayProfileImage(holder.my_profile_image, status.user_profile_image_url);
loader.displayProfileImage(holder.profile_image, status.user_profile_image_url);
holder.profile_image.setTag(position);
holder.my_profile_image.setTag(position);
} else {
loader.cancelDisplayTask(holder.profile_image);
loader.cancelDisplayTask(holder.my_profile_image);
holder.profile_image.setVisibility(View.GONE);
holder.my_profile_image.setVisibility(View.GONE);
}
final boolean hasPreview = mDisplayImagePreview && hasMedia;
holder.image_preview_container.setVisibility(hasPreview ? View.VISIBLE : View.GONE);
if (hasPreview) {
if (mImagePreviewScaleType != null) {
holder.image_preview.setScaleType(mImagePreviewScaleType);
}
if (status.is_possibly_sensitive && !mDisplaySensitiveContents) {
holder.image_preview.setImageDrawable(null);
holder.image_preview.setBackgroundResource(R.drawable.image_preview_nsfw);
holder.image_preview_progress.setVisibility(View.GONE);
} else if (!status.first_media.equals(mImageLoadingHandler.getLoadingUri(holder.image_preview))) {
holder.image_preview.setBackgroundResource(0);
loader.displayPreviewImage(holder.image_preview, status.first_media, mImageLoadingHandler);
}
final int count = status.media.length;
holder.image_preview_count.setText(res.getQuantityString(R.plurals.N_media, count, count));
holder.image_preview.setTag(position);
} else {
loader.cancelDisplayTask(holder.image_preview);
}
} else {
loader.cancelDisplayTask(holder.profile_image);
loader.cancelDisplayTask(holder.my_profile_image);
loader.cancelDisplayTask(holder.image_preview);
}
if (position > mMaxAnimationPosition) {
if (mAnimationEnabled) {
view.startAnimation(holder.item_animation);
}
mMaxAnimationPosition = position;
}
holder.displayStatus(status);
return view;
}
@Override
public boolean isGapItem(int position) {
return false;
}
@Override
public void onGapClick(StatusViewHolder holder, int position) {
}
@Override
public boolean isLastItemFiltered() {
return mIsLastItemFiltered;
@ -447,6 +335,7 @@ public class ParcelableStatusesListAdapter extends BaseArrayAdapter<ParcelableSt
}
private static int getItemResource(final boolean compactCards) {
return compactCards ? R.layout.card_item_status_compact : R.layout.card_item_status;
return compactCards ? R.layout.card_item_list_status_compat : R.layout.card_item_list_status;
}
}

View File

@ -56,15 +56,13 @@ public class ParcelableUserListsAdapter extends BaseArrayAdapter<ParcelableUserL
private boolean mAnimationEnabled;
private int mMaxAnimationPosition;
private final boolean mPlainList;
public ParcelableUserListsAdapter(final Context context) {
this(context, Utils.isCompactCards(context), Utils.isPlainListStyle(context));
this(context, Utils.isCompactCards(context));
}
public ParcelableUserListsAdapter(final Context context, final boolean compactCards, final boolean plainList) {
public ParcelableUserListsAdapter(final Context context, final boolean compactCards) {
super(context, getItemResource(compactCards));
mPlainList = plainList;
mContext = context;
mLocale = context.getResources().getConfiguration().locale;
final TwidereApplication app = TwidereApplication.getInstance(context);
@ -93,10 +91,6 @@ public class ParcelableUserListsAdapter extends BaseArrayAdapter<ParcelableUserL
holder = new UserListViewHolder(view);
holder.profile_image.setOnClickListener(this);
holder.content.setOnOverflowIconClickListener(this);
if (mPlainList) {
((View) holder.content).setPadding(0, 0, 0, 0);
holder.content.setItemBackground(null);
}
view.setTag(holder);
}

View File

@ -53,18 +53,16 @@ public class ParcelableUsersAdapter extends BaseArrayAdapter<ParcelableUser> imp
private MenuButtonClickListener mListener;
private final Locale mLocale;
private final boolean mPlainList;
private boolean mAnimationEnabled;
private int mMaxAnimationPosition;
public ParcelableUsersAdapter(final Context context) {
this(context, Utils.isCompactCards(context), Utils.isPlainListStyle(context));
this(context, Utils.isCompactCards(context));
}
public ParcelableUsersAdapter(final Context context, final boolean compactCards, final boolean plainList) {
public ParcelableUsersAdapter(final Context context, final boolean compactCards) {
super(context, getItemResource(compactCards));
mPlainList = plainList;
mContext = context;
mLocale = context.getResources().getConfiguration().locale;
final TwidereApplication app = TwidereApplication.getInstance(context);
@ -88,10 +86,6 @@ public class ParcelableUsersAdapter extends BaseArrayAdapter<ParcelableUser> imp
} else {
holder = new UserViewHolder(view);
holder.content.setOnOverflowIconClickListener(this);
if (mPlainList) {
((View) holder.content).setPadding(0, 0, 0, 0);
holder.content.setItemBackground(null);
}
view.setTag(holder);
}

View File

@ -0,0 +1,33 @@
/*
* 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 android.support.v7.widget.RecyclerView.ViewHolder;
/**
* Created by mariotaku on 14/12/3.
*/
public interface IGapSupportedAdapter<VH extends ViewHolder> {
boolean isGapItem(int position);
void onGapClick(VH holder, int position);
}

View File

@ -0,0 +1,29 @@
/*
* 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 android.support.v7.widget.RecyclerView.ViewHolder;
/**
* Created by mariotaku on 14/12/3.
*/
public interface IItemMenuSupportedAdapter<VH extends ViewHolder> {
void onItemMenuClick(VH holder, int position);
}

View File

@ -5,11 +5,13 @@ import android.content.Context;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.ImageLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.view.holder.StatusViewHolder;
/**
* Created by mariotaku on 14/11/18.
*/
public interface IStatusesAdapter {
public interface IStatusesAdapter<Data> extends IGapSupportedAdapter<StatusViewHolder>,
IItemMenuSupportedAdapter<StatusViewHolder> {
ImageLoaderWrapper getImageLoader();
@ -20,4 +22,10 @@ public interface IStatusesAdapter {
ParcelableStatus getStatus(int position);
int getStatusCount();
void onStatusClick(StatusViewHolder holder, int position);
void onUserProfileClick(StatusViewHolder holder, int position);
void setData(Data data);
}

View File

@ -21,7 +21,7 @@ package org.mariotaku.twidere.adapter.iface;
import org.mariotaku.twidere.model.ParcelableStatus;
public interface IStatusesListAdapter<Data> extends IBaseCardAdapter, IStatusesAdapter {
public interface IStatusesListAdapter<Data> extends IBaseCardAdapter, IStatusesAdapter<Data> {
public int findPositionByStatusId(final long statusId);
@ -31,16 +31,12 @@ public interface IStatusesListAdapter<Data> extends IBaseCardAdapter, IStatusesA
public long getLastStatusId();
public ParcelableStatus getStatus(int position);
public long getStatusId(final int position);
public boolean isLastItemFiltered();
public void setCardHighlightOption(String option);
public void setData(Data data);
public void setDisplayImagePreview(boolean display);
public void setDisplaySensitiveContents(boolean display);

View File

@ -281,8 +281,6 @@ public interface SharedPreferenceConstants {
@Preference(type = STRING, hasDefault = true, defaultString = "CENTER_CROP")
public static final String KEY_IMAGE_PREVIEW_SCALE_TYPE = "image_preview_scale_type";
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = false)
public static final String KEY_PLAIN_LIST_STYLE = "plain_list_style";
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = false)
public static final String KEY_SORT_TIMELINE_BY_ID = "sort_timeline_by_id";
public static final String KEY_QUICK_MENU_EXPANDED = "quick_menu_expanded";

View File

@ -0,0 +1,187 @@
package org.mariotaku.twidere.fragment.support;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager;
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.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.OnScrollListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.AbsStatusesAdapter;
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration;
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 14/11/5.
*/
public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment
implements LoaderCallbacks<Data>, OnRefreshListener, DrawerCallback {
private View mContentView;
private SharedPreferences mPreferences;
@Override
public void fling(float velocity) {
mDrawerCallback.fling(velocity);
}
public abstract int getStatuses(long[] accountIds, long[] maxIds, long[] sinceIds);
@Override
public void scrollBy(float dy) {
mDrawerCallback.scrollBy(dy);
}
@Override
public boolean shouldLayoutHeaderBottom() {
return mDrawerCallback.shouldLayoutHeaderBottom();
}
@Override
public boolean canScroll(float dy) {
return mDrawerCallback.canScroll(dy);
}
@Override
public boolean isScrollContent(float x, float y) {
return mDrawerCallback.isScrollContent(x, y);
}
@Override
public void cancelTouch() {
mDrawerCallback.cancelTouch();
}
@Override
public void topChanged(int offset) {
mDrawerCallback.topChanged(offset);
}
private View mProgressContainer;
private SwipeRefreshLayout mSwipeRefreshLayout;
private RecyclerView mRecyclerView;
private AbsStatusesAdapter<Data> mAdapter;
private SimpleDrawerCallback mDrawerCallback;
private OnScrollListener mOnScrollListener = new OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
final LoaderManager lm = getLoaderManager();
if (lm.hasRunningLoaders()) return;
if (layoutManager.findLastVisibleItemPosition() == mAdapter.getItemCount() - 1) {
final long[] maxIds = new long[]{mAdapter.getStatus(mAdapter.getStatusCount() - 1).id};
getStatuses(null, maxIds, null);
}
}
};
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
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));
mAdapter = onCreateAdapter(context, compact);
final LinearLayoutManager layoutManager = new LinearLayoutManager(context);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
if (compact) {
mRecyclerView.addItemDecoration(new DividerItemDecoration(context, layoutManager.getOrientation()));
}
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setOnScrollListener(mOnScrollListener);
getLoaderManager().initLoader(0, getArguments(), this);
setListShown(false);
}
protected abstract AbsStatusesAdapter<Data> onCreateAdapter(Context context, boolean compact);
private void setListShown(boolean shown) {
mProgressContainer.setVisibility(shown ? View.GONE : View.VISIBLE);
mSwipeRefreshLayout.setVisibility(shown ? View.VISIBLE : View.GONE);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
mContentView = view.findViewById(R.id.fragment_content);
mProgressContainer = view.findViewById(R.id.progress_container);
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_layout);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
super.onViewCreated(view, savedInstanceState);
}
@Override
protected void fitSystemWindows(Rect insets) {
super.fitSystemWindows(insets);
mContentView.setPadding(insets.left, insets.top, insets.right, insets.bottom);
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_recycler_view, container, false);
}
protected Data getAdapterData() {
return mAdapter.getData();
}
public void setRefreshing(boolean refreshing) {
mSwipeRefreshLayout.setRefreshing(refreshing);
}
@Override
public void onLoadFinished(Loader<Data> loader, Data data) {
setRefreshing(false);
mAdapter.setData(data);
setListShown(true);
}
@Override
public void onLoaderReset(Loader<Data> loader) {
}
@Override
public void onRefresh() {
if (mAdapter.getStatusCount() > 0) {
final long[] sinceIds = new long[]{mAdapter.getStatus(0).id};
getStatuses(null, null, sinceIds);
} else {
getStatuses(null, null, null);
}
}
public SharedPreferences getSharedPreferences() {
if (mPreferences != null) return mPreferences;
return mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
}
}

View File

@ -122,14 +122,14 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
mAppMenuAdapter = new AppMenuAdapter(context);
mAppMenuSectionView = newSectionView(context, R.string.more);
mAccountSelectorView = inflater.inflate(R.layout.header_drawer_account_selector, listView, false);
mAccountsSelector = (RecyclerView) mAccountSelectorView.findViewById(R.id.account_selector);
mAccountsSelector = (RecyclerView) mAccountSelectorView.findViewById(R.id.other_accounts_list);
final LinearLayoutManager layoutManager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
layoutManager.setStackFromEnd(true);
mAccountsSelector.setLayoutManager(layoutManager);
mAccountsSelector.setAdapter(mAccountsAdapter);
mAccountProfileContainer = mAccountSelectorView.findViewById(R.id.profile_container);
mAccountProfileImageView = (ImageView) mAccountSelectorView.findViewById(R.id.profile_image);
mAccountProfileBannerView = (ImageView) mAccountSelectorView.findViewById(R.id.profile_banner);
mAccountProfileBannerView = (ImageView) mAccountSelectorView.findViewById(R.id.account_profile_banner);
mAccountProfileNameView = (TextView) mAccountSelectorView.findViewById(R.id.name);
mAccountProfileScreenNameView = (TextView) mAccountSelectorView.findViewById(R.id.screen_name);
mAccountsToggle = (Switch) mAccountSelectorView.findViewById(R.id.toggle);

View File

@ -19,10 +19,6 @@
package org.mariotaku.twidere.fragment.support;
import static org.mariotaku.twidere.util.Utils.openStatus;
import static org.mariotaku.twidere.util.Utils.openUserProfile;
import static org.mariotaku.twidere.util.Utils.openUsers;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.content.Loader;
@ -39,81 +35,84 @@ import org.mariotaku.twidere.model.ParcelableUser;
import java.util.Arrays;
import java.util.List;
import static org.mariotaku.twidere.util.Utils.openStatus;
import static org.mariotaku.twidere.util.Utils.openUserProfile;
import static org.mariotaku.twidere.util.Utils.openUsers;
public class ActivitiesAboutMeFragment extends BaseActivitiesListFragment {
@Override
public BaseParcelableActivitiesAdapter createListAdapter(final Context context, final boolean compactCards,
final boolean plainListStyle) {
return new ParcelableActivitiesAboutMeAdapter(context, compactCards, plainListStyle);
}
@Override
public BaseParcelableActivitiesAdapter createListAdapter(final Context context, final boolean compactCards) {
return new ParcelableActivitiesAboutMeAdapter(context, compactCards);
}
@Override
public Loader<List<ParcelableActivity>> onCreateLoader(final int id, final Bundle args) {
setProgressBarIndeterminateVisibility(true);
return new ActivitiesAboutMeLoader(getActivity(), getAccountIds(), getData(), getSavedActivitiesFileArgs(),
true);
}
@Override
public Loader<List<ParcelableActivity>> onCreateLoader(final int id, final Bundle args) {
setProgressBarIndeterminateVisibility(true);
return new ActivitiesAboutMeLoader(getActivity(), getAccountIds(), getData(), getSavedActivitiesFileArgs(),
true);
}
@Override
public void onListItemClick(final ListView l, final View v, final int position, final long id) {
final int adapter_pos = position - l.getHeaderViewsCount();
final ParcelableActivity item = getListAdapter().getItem(adapter_pos);
if (item == null) return;
final ParcelableUser[] sources = item.sources;
if (sources == null || sources.length == 0) return;
final ParcelableStatus[] target_statuses = item.target_statuses;
final ParcelableStatus[] target_objects = item.target_object_statuses;
switch (item.action) {
case ParcelableActivity.ACTION_FAVORITE: {
if (sources.length == 1) {
openUserProfile(getActivity(), sources[0], null);
} else {
final List<ParcelableUser> users = Arrays.asList(sources);
openUsers(getActivity(), users);
}
break;
}
case ParcelableActivity.ACTION_FOLLOW: {
if (sources.length == 1) {
openUserProfile(getActivity(), sources[0], null);
} else {
final List<ParcelableUser> users = Arrays.asList(sources);
openUsers(getActivity(), users);
}
break;
}
case ParcelableActivity.ACTION_MENTION: {
if (target_objects != null && target_objects.length > 0) {
openStatus(getActivity(), target_objects[0]);
}
break;
}
case ParcelableActivity.ACTION_REPLY: {
if (target_statuses != null && target_statuses.length > 0) {
openStatus(getActivity(), target_statuses[0]);
}
break;
}
case ParcelableActivity.ACTION_RETWEET: {
if (sources.length == 1) {
openUserProfile(getActivity(), sources[0], null);
} else {
final List<ParcelableUser> users = Arrays.asList(sources);
openUsers(getActivity(), users);
}
break;
}
}
}
@Override
public void onListItemClick(final ListView l, final View v, final int position, final long id) {
final int adapter_pos = position - l.getHeaderViewsCount();
final ParcelableActivity item = getListAdapter().getItem(adapter_pos);
if (item == null) return;
final ParcelableUser[] sources = item.sources;
if (sources == null || sources.length == 0) return;
final ParcelableStatus[] target_statuses = item.target_statuses;
final ParcelableStatus[] target_objects = item.target_object_statuses;
switch (item.action) {
case ParcelableActivity.ACTION_FAVORITE: {
if (sources.length == 1) {
openUserProfile(getActivity(), sources[0], null);
} else {
final List<ParcelableUser> users = Arrays.asList(sources);
openUsers(getActivity(), users);
}
break;
}
case ParcelableActivity.ACTION_FOLLOW: {
if (sources.length == 1) {
openUserProfile(getActivity(), sources[0], null);
} else {
final List<ParcelableUser> users = Arrays.asList(sources);
openUsers(getActivity(), users);
}
break;
}
case ParcelableActivity.ACTION_MENTION: {
if (target_objects != null && target_objects.length > 0) {
openStatus(getActivity(), target_objects[0], null);
}
break;
}
case ParcelableActivity.ACTION_REPLY: {
if (target_statuses != null && target_statuses.length > 0) {
openStatus(getActivity(), target_statuses[0], null);
}
break;
}
case ParcelableActivity.ACTION_RETWEET: {
if (sources.length == 1) {
openUserProfile(getActivity(), sources[0], null);
} else {
final List<ParcelableUser> users = Arrays.asList(sources);
openUsers(getActivity(), users);
}
break;
}
}
}
@Override
protected String[] getSavedActivitiesFileArgs() {
final Bundle args = getArguments();
if (args != null && args.containsKey(EXTRA_ACCOUNT_ID)) {
final long account_id = args.getLong(EXTRA_ACCOUNT_ID, -1);
return new String[] { AUTHORITY_ACTIVITIES_ABOUT_ME, "account" + account_id };
}
return new String[] { AUTHORITY_ACTIVITIES_ABOUT_ME };
}
@Override
protected String[] getSavedActivitiesFileArgs() {
final Bundle args = getArguments();
if (args != null && args.containsKey(EXTRA_ACCOUNT_ID)) {
final long account_id = args.getLong(EXTRA_ACCOUNT_ID, -1);
return new String[]{AUTHORITY_ACTIVITIES_ABOUT_ME, "account" + account_id};
}
return new String[]{AUTHORITY_ACTIVITIES_ABOUT_ME};
}
}

View File

@ -19,11 +19,6 @@
package org.mariotaku.twidere.fragment.support;
import static org.mariotaku.twidere.util.Utils.openStatus;
import static org.mariotaku.twidere.util.Utils.openStatuses;
import static org.mariotaku.twidere.util.Utils.openUserProfile;
import static org.mariotaku.twidere.util.Utils.openUsers;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.content.Loader;
@ -40,85 +35,89 @@ import org.mariotaku.twidere.model.ParcelableUser;
import java.util.Arrays;
import java.util.List;
import static org.mariotaku.twidere.util.Utils.openStatus;
import static org.mariotaku.twidere.util.Utils.openStatuses;
import static org.mariotaku.twidere.util.Utils.openUserProfile;
import static org.mariotaku.twidere.util.Utils.openUsers;
public class ActivitiesByFriendsFragment extends BaseActivitiesListFragment {
@Override
public BaseParcelableActivitiesAdapter createListAdapter(final Context context, final boolean compactCards,
final boolean plainListStyle) {
return new ParcelableActivitiesByFriendsAdapter(context, compactCards, plainListStyle);
}
@Override
public BaseParcelableActivitiesAdapter createListAdapter(final Context context, final boolean compactCards) {
return new ParcelableActivitiesByFriendsAdapter(context, compactCards);
}
@Override
public Loader<List<ParcelableActivity>> onCreateLoader(final int id, final Bundle args) {
setProgressBarIndeterminateVisibility(true);
return new ActivitiesAboutMeLoader(getActivity(), getAccountIds(), getData(), getSavedActivitiesFileArgs(),
getTabPosition() >= 0);
}
@Override
public Loader<List<ParcelableActivity>> onCreateLoader(final int id, final Bundle args) {
setProgressBarIndeterminateVisibility(true);
return new ActivitiesAboutMeLoader(getActivity(), getAccountIds(), getData(), getSavedActivitiesFileArgs(),
getTabPosition() >= 0);
}
@Override
public void onListItemClick(final ListView l, final View v, final int position, final long id) {
final int adapterPos = position - l.getHeaderViewsCount();
final ParcelableActivity item = getListAdapter().getItem(adapterPos);
if (item == null) return;
final ParcelableUser[] sources = item.sources;
if (sources == null || sources.length == 0) return;
final ParcelableStatus[] targetStatuses = item.target_statuses;
final ParcelableUser[] targetUsers = item.target_users;
final ParcelableStatus[] target_object_statuses = item.target_object_statuses;
switch (item.action) {
case ParcelableActivity.ACTION_FAVORITE: {
if (targetStatuses == null || targetStatuses.length == 0) return;
if (targetStatuses.length == 1) {
openStatus(getActivity(), targetStatuses[0]);
} else {
final List<ParcelableStatus> statuses = Arrays.asList(targetStatuses);
openStatuses(getActivity(), statuses);
}
break;
}
case ParcelableActivity.ACTION_FOLLOW: {
if (targetUsers == null || targetUsers.length == 0) return;
if (targetUsers.length == 1) {
openUserProfile(getActivity(), targetUsers[0], null);
} else {
final List<ParcelableUser> users = Arrays.asList(targetUsers);
openUsers(getActivity(), users);
}
break;
}
case ParcelableActivity.ACTION_MENTION: {
if (target_object_statuses != null && target_object_statuses.length > 0) {
openStatus(getActivity(), target_object_statuses[0]);
}
break;
}
case ParcelableActivity.ACTION_REPLY: {
if (targetStatuses != null && targetStatuses.length > 0) {
openStatus(getActivity(), targetStatuses[0]);
}
break;
}
case ParcelableActivity.ACTION_RETWEET: {
if (targetStatuses == null || targetStatuses.length == 0) return;
if (targetStatuses.length == 1) {
openStatus(getActivity(), targetStatuses[0]);
} else {
final List<ParcelableStatus> statuses = Arrays.asList(targetStatuses);
openStatuses(getActivity(), statuses);
}
break;
}
}
}
@Override
public void onListItemClick(final ListView l, final View v, final int position, final long id) {
final int adapterPos = position - l.getHeaderViewsCount();
final ParcelableActivity item = getListAdapter().getItem(adapterPos);
if (item == null) return;
final ParcelableUser[] sources = item.sources;
if (sources == null || sources.length == 0) return;
final ParcelableStatus[] targetStatuses = item.target_statuses;
final ParcelableUser[] targetUsers = item.target_users;
final ParcelableStatus[] target_object_statuses = item.target_object_statuses;
switch (item.action) {
case ParcelableActivity.ACTION_FAVORITE: {
if (targetStatuses == null || targetStatuses.length == 0) return;
if (targetStatuses.length == 1) {
openStatus(getActivity(), targetStatuses[0], null);
} else {
final List<ParcelableStatus> statuses = Arrays.asList(targetStatuses);
openStatuses(getActivity(), statuses);
}
break;
}
case ParcelableActivity.ACTION_FOLLOW: {
if (targetUsers == null || targetUsers.length == 0) return;
if (targetUsers.length == 1) {
openUserProfile(getActivity(), targetUsers[0], null);
} else {
final List<ParcelableUser> users = Arrays.asList(targetUsers);
openUsers(getActivity(), users);
}
break;
}
case ParcelableActivity.ACTION_MENTION: {
if (target_object_statuses != null && target_object_statuses.length > 0) {
openStatus(getActivity(), target_object_statuses[0], null);
}
break;
}
case ParcelableActivity.ACTION_REPLY: {
if (targetStatuses != null && targetStatuses.length > 0) {
openStatus(getActivity(), targetStatuses[0], null);
}
break;
}
case ParcelableActivity.ACTION_RETWEET: {
if (targetStatuses == null || targetStatuses.length == 0) return;
if (targetStatuses.length == 1) {
openStatus(getActivity(), targetStatuses[0], null);
} else {
final List<ParcelableStatus> statuses = Arrays.asList(targetStatuses);
openStatuses(getActivity(), statuses);
}
break;
}
}
}
@Override
protected String[] getSavedActivitiesFileArgs() {
final Bundle args = getArguments();
if (args != null && args.containsKey(EXTRA_ACCOUNT_ID)) {
final long account_id = args.getLong(EXTRA_ACCOUNT_ID, -1);
return new String[] { AUTHORITY_ACTIVITIES_BY_FRIENDS, "account" + account_id };
}
return new String[] { AUTHORITY_ACTIVITIES_BY_FRIENDS };
}
@Override
protected String[] getSavedActivitiesFileArgs() {
final Bundle args = getArguments();
if (args != null && args.containsKey(EXTRA_ACCOUNT_ID)) {
final long account_id = args.getLong(EXTRA_ACCOUNT_ID, -1);
return new String[]{AUTHORITY_ACTIVITIES_BY_FRIENDS, "account" + account_id};
}
return new String[]{AUTHORITY_ACTIVITIES_BY_FRIENDS};
}
}

View File

@ -19,9 +19,6 @@
package org.mariotaku.twidere.fragment.support;
import static org.mariotaku.twidere.util.Utils.encodeQueryParams;
import static org.mariotaku.twidere.util.Utils.getDefaultTextSize;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
@ -38,102 +35,105 @@ import org.mariotaku.twidere.util.Utils;
import java.io.IOException;
import java.util.List;
import static org.mariotaku.twidere.util.Utils.encodeQueryParams;
import static org.mariotaku.twidere.util.Utils.getDefaultTextSize;
public abstract class BaseActivitiesListFragment extends BasePullToRefreshListFragment implements
LoaderCallbacks<List<ParcelableActivity>> {
LoaderCallbacks<List<ParcelableActivity>> {
private BaseParcelableActivitiesAdapter mAdapter;
private SharedPreferences mPreferences;
private BaseParcelableActivitiesAdapter mAdapter;
private SharedPreferences mPreferences;
private List<ParcelableActivity> mData;
private List<ParcelableActivity> mData;
public abstract BaseParcelableActivitiesAdapter createListAdapter(Context context, boolean compactCards,
boolean plainListStyle);
public abstract BaseParcelableActivitiesAdapter createListAdapter(final Context context,
final boolean compactCards);
@Override
public BaseParcelableActivitiesAdapter getListAdapter() {
return mAdapter;
}
@Override
public BaseParcelableActivitiesAdapter getListAdapter() {
return mAdapter;
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
final boolean plainListStyle = mPreferences.getBoolean(KEY_PLAIN_LIST_STYLE, false);
final boolean compactCards = mPreferences.getBoolean(KEY_COMPACT_CARDS, false);
mAdapter = createListAdapter(getActivity(), compactCards, plainListStyle);
setListAdapter(mAdapter);
final ListView lv = getListView();
if (!plainListStyle) {
lv.setDivider(null);
}
lv.setSelector(android.R.color.transparent);
getLoaderManager().initLoader(0, getArguments(), this);
setListShown(false);
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
final boolean compactCards = mPreferences.getBoolean(KEY_COMPACT_CARDS, false);
mAdapter = createListAdapter(getActivity(), compactCards);
setListAdapter(mAdapter);
final ListView lv = getListView();
if (!compactCards) {
lv.setDivider(null);
}
lv.setSelector(android.R.color.transparent);
getLoaderManager().initLoader(0, getArguments(), this);
setListShown(false);
}
@Override
public void onLoaderReset(final Loader<List<ParcelableActivity>> loader) {
mAdapter.setData(null);
mData = null;
}
@Override
public void onLoaderReset(final Loader<List<ParcelableActivity>> loader) {
mAdapter.setData(null);
mData = null;
}
@Override
public void onLoadFinished(final Loader<List<ParcelableActivity>> loader, final List<ParcelableActivity> data) {
setProgressBarIndeterminateVisibility(false);
setRefreshComplete();
mData = data;
mAdapter.setData(data);
if (loader instanceof Twitter4JActivitiesLoader) {
final boolean multipleAccounts = ((Twitter4JActivitiesLoader) loader).getAccountIds().length > 1;
mAdapter.setShowAccountColor(multipleAccounts);
}
setRefreshComplete();
setListShown(true);
}
@Override
public void onLoadFinished(final Loader<List<ParcelableActivity>> loader, final List<ParcelableActivity> data) {
setProgressBarIndeterminateVisibility(false);
setRefreshComplete();
mData = data;
mAdapter.setData(data);
if (loader instanceof Twitter4JActivitiesLoader) {
final boolean multipleAccounts = ((Twitter4JActivitiesLoader) loader).getAccountIds().length > 1;
mAdapter.setShowAccountColor(multipleAccounts);
}
setRefreshComplete();
setListShown(true);
}
@Override
public void onRefreshFromEnd() {
@Override
public void onRefreshFromEnd() {
}
}
@Override
public void onRefreshFromStart() {
if (isRefreshing()) return;
getLoaderManager().restartLoader(0, getArguments(), this);
}
@Override
public void onRefreshFromStart() {
if (isRefreshing()) return;
getLoaderManager().restartLoader(0, getArguments(), this);
}
@Override
public void onResume() {
super.onResume();
final float text_size = mPreferences.getInt(KEY_TEXT_SIZE, getDefaultTextSize(getActivity()));
final boolean display_profile_image = mPreferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true);
final boolean show_absolute_time = mPreferences.getBoolean(KEY_SHOW_ABSOLUTE_TIME, false);
mAdapter.setDisplayProfileImage(display_profile_image);
mAdapter.setTextSize(text_size);
mAdapter.setShowAbsoluteTime(show_absolute_time);
}
@Override
public void onResume() {
super.onResume();
final float text_size = mPreferences.getInt(KEY_TEXT_SIZE, getDefaultTextSize(getActivity()));
final boolean display_profile_image = mPreferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true);
final boolean show_absolute_time = mPreferences.getBoolean(KEY_SHOW_ABSOLUTE_TIME, false);
mAdapter.setDisplayProfileImage(display_profile_image);
mAdapter.setTextSize(text_size);
mAdapter.setShowAbsoluteTime(show_absolute_time);
}
protected final long[] getAccountIds() {
final Bundle args = getArguments();
if (args != null && args.containsKey(EXTRA_ACCOUNT_ID)) return new long[] { args.getLong(EXTRA_ACCOUNT_ID) };
return Utils.getActivatedAccountIds(getActivity());
}
protected final long[] getAccountIds() {
final Bundle args = getArguments();
if (args != null && args.containsKey(EXTRA_ACCOUNT_ID))
return new long[]{args.getLong(EXTRA_ACCOUNT_ID)};
return Utils.getActivatedAccountIds(getActivity());
}
protected final List<ParcelableActivity> getData() {
return mData;
}
protected final List<ParcelableActivity> getData() {
return mData;
}
protected final String getPositionKey() {
final Object[] args = getSavedActivitiesFileArgs();
if (args == null || args.length <= 0) return null;
try {
return encodeQueryParams(ArrayUtils.toString(args, '.', false) + "." + getTabPosition());
} catch (final IOException e) {
e.printStackTrace();
}
return null;
}
protected final String getPositionKey() {
final Object[] args = getSavedActivitiesFileArgs();
if (args == null || args.length <= 0) return null;
try {
return encodeQueryParams(ArrayUtils.toString(args, '.', false) + "." + getTabPosition());
} catch (final IOException e) {
e.printStackTrace();
}
return null;
}
protected abstract Object[] getSavedActivitiesFileArgs();
protected abstract Object[] getSavedActivitiesFileArgs();
}

View File

@ -137,14 +137,13 @@ abstract class BaseStatusesListFragment<Data> extends BasePullToRefreshListFragm
mPositionManager = new PositionManager(context);
mMultiSelectManager = getMultiSelectManager();
mListView = getListView();
final boolean plainListStyle = mPreferences.getBoolean(KEY_PLAIN_LIST_STYLE, false);
final boolean compactCards = mPreferences.getBoolean(KEY_COMPACT_CARDS, false);
mAdapter = newAdapterInstance(compactCards, plainListStyle);
mAdapter = newAdapterInstance(compactCards);
mAdapter.setMenuButtonClickListener(this);
setListAdapter(null);
setListHeaderFooters(mListView);
setListAdapter(mAdapter);
if (!plainListStyle) {
if (!compactCards) {
mListView.setDivider(null);
}
mListView.setSelector(android.R.color.transparent);
@ -291,7 +290,7 @@ abstract class BaseStatusesListFragment<Data> extends BasePullToRefreshListFragm
if (status == null || twitter == null) return false;
switch (item.getItemId()) {
case MENU_VIEW: {
openStatus(getActivity(), status);
openStatus(getActivity(), status, null);
break;
}
case MENU_SHARE: {
@ -480,7 +479,7 @@ abstract class BaseStatusesListFragment<Data> extends BasePullToRefreshListFragm
protected abstract void loadMoreStatuses();
protected abstract IStatusesListAdapter<Data> newAdapterInstance(boolean compact, boolean plain);
protected abstract IStatusesListAdapter<Data> newAdapterInstance(boolean compact);
@Override
protected void onReachedBottom() {

View File

@ -203,7 +203,7 @@ abstract class BaseStatusesStaggeredGridFragment<Data> extends BasePullToRefresh
setItemSelected(status, position, !mMultiSelectManager.isSelected(status));
return;
}
openStatus(getActivity(), status);
openStatus(getActivity(), status, null);
}
}
}
@ -281,7 +281,7 @@ abstract class BaseStatusesStaggeredGridFragment<Data> extends BasePullToRefresh
if (status == null || twitter == null) return false;
switch (item.getItemId()) {
case MENU_VIEW: {
openStatus(getActivity(), status);
openStatus(getActivity(), status, null);
break;
}
case MENU_SHARE: {

View File

@ -114,7 +114,7 @@ abstract class BaseUsersListFragment extends BasePullToRefreshListFragment imple
mData.clear();
}
mAccountId = accountId;
if (!mPreferences.getBoolean(KEY_PLAIN_LIST_STYLE, false)) {
if (!mPreferences.getBoolean(KEY_COMPACT_CARDS, false)) {
mListView.setDivider(null);
}
mListView.setSelector(android.R.color.transparent);

View File

@ -0,0 +1,37 @@
/*
* 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.database.Cursor;
import org.mariotaku.twidere.adapter.CursorStatusesAdapter;
/**
* Created by mariotaku on 14/12/3.
*/
public abstract class CursorStatusesFragment extends AbsStatusesFragment<Cursor> {
@Override
protected CursorStatusesAdapter onCreateAdapter(final Context context, final boolean compact) {
return new CursorStatusesAdapter(context, compact);
}
}

View File

@ -35,7 +35,7 @@ import org.mariotaku.querybuilder.RawItemArray;
import org.mariotaku.querybuilder.Where;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.support.HomeActivity;
import org.mariotaku.twidere.adapter.CursorStatusesAdapter;
import org.mariotaku.twidere.adapter.CursorStatusesListAdapter;
import org.mariotaku.twidere.provider.TweetStore.Accounts;
import org.mariotaku.twidere.provider.TweetStore.Filters;
import org.mariotaku.twidere.provider.TweetStore.Statuses;
@ -92,7 +92,7 @@ public abstract class CursorStatusesListFragment extends BaseStatusesListFragmen
where = accountWhere;
}
final String selection = processWhere(where).getSQL();
return new CursorLoader(context, uri, CursorStatusesAdapter.CURSOR_COLS, selection, null, sortOrder);
return new CursorLoader(context, uri, CursorStatusesListAdapter.CURSOR_COLS, selection, null, sortOrder);
}
@Override
@ -206,8 +206,8 @@ public abstract class CursorStatusesListFragment extends BaseStatusesListFragmen
}
@Override
protected CursorStatusesAdapter newAdapterInstance(final boolean compact, final boolean plain) {
return new CursorStatusesAdapter(getActivity(), compact, plain);
protected CursorStatusesListAdapter newAdapterInstance(final boolean compact) {
return new CursorStatusesListAdapter(getActivity(), compact);
}
@Override

View File

@ -40,7 +40,7 @@ import org.mariotaku.querybuilder.RawItemArray;
import org.mariotaku.querybuilder.Where;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.support.HomeActivity;
import org.mariotaku.twidere.adapter.CursorStatusesAdapter;
import org.mariotaku.twidere.adapter.CursorStatusesListAdapter;
import org.mariotaku.twidere.provider.TweetStore.Accounts;
import org.mariotaku.twidere.provider.TweetStore.Filters;
import org.mariotaku.twidere.provider.TweetStore.Statuses;
@ -86,7 +86,7 @@ public abstract class CursorStatusesStaggeredGridFragment extends BaseStatusesSt
} else {
where = accountWhere;
}
return new CursorLoader(getActivity(), uri, CursorStatusesAdapter.CURSOR_COLS, where.getSQL(), null, sort_by);
return new CursorLoader(getActivity(), uri, CursorStatusesListAdapter.CURSOR_COLS, where.getSQL(), null, sort_by);
}
@Override
@ -194,8 +194,8 @@ public abstract class CursorStatusesStaggeredGridFragment extends BaseStatusesSt
}
@Override
protected CursorStatusesAdapter newAdapterInstance() {
return new CursorStatusesAdapter(getActivity());
protected CursorStatusesListAdapter newAdapterInstance() {
return new CursorStatusesListAdapter(getActivity());
}
@Override

View File

@ -19,12 +19,6 @@
package org.mariotaku.twidere.fragment.support;
import static org.mariotaku.twidere.util.Utils.configBaseCardAdapter;
import static org.mariotaku.twidere.util.Utils.getActivatedAccountIds;
import static org.mariotaku.twidere.util.Utils.getNewestMessageIdsFromDatabase;
import static org.mariotaku.twidere.util.Utils.getOldestMessageIdsFromDatabase;
import static org.mariotaku.twidere.util.Utils.openDirectMessagesConversation;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@ -61,316 +55,323 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static org.mariotaku.twidere.util.Utils.configBaseCardAdapter;
import static org.mariotaku.twidere.util.Utils.getActivatedAccountIds;
import static org.mariotaku.twidere.util.Utils.getNewestMessageIdsFromDatabase;
import static org.mariotaku.twidere.util.Utils.getOldestMessageIdsFromDatabase;
import static org.mariotaku.twidere.util.Utils.openDirectMessagesConversation;
public class DirectMessagesFragment extends BasePullToRefreshListFragment implements LoaderCallbacks<Cursor> {
private final SupportFragmentReloadCursorObserver mReloadContentObserver = new SupportFragmentReloadCursorObserver(
this, 0, this);
private final SupportFragmentReloadCursorObserver mReloadContentObserver = new SupportFragmentReloadCursorObserver(
this, 0, this);
private final BroadcastReceiver mStatusReceiver = new BroadcastReceiver() {
private final BroadcastReceiver mStatusReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
if (getActivity() == null || !isAdded() || isDetached()) return;
final String action = intent.getAction();
if (BROADCAST_TASK_STATE_CHANGED.equals(action)) {
updateRefreshState();
}
}
};
@Override
public void onReceive(final Context context, final Intent intent) {
if (getActivity() == null || !isAdded() || isDetached()) return;
final String action = intent.getAction();
if (BROADCAST_TASK_STATE_CHANGED.equals(action)) {
updateRefreshState();
}
}
};
private MultiSelectManager mMultiSelectManager;
private MultiSelectManager mMultiSelectManager;
private SharedPreferences mPreferences;
private ListView mListView;
private SharedPreferences mPreferences;
private ListView mListView;
private boolean mLoadMoreAutomatically;
private boolean mLoadMoreAutomatically;
private DirectMessageConversationEntriesAdapter mAdapter;
private int mFirstVisibleItem;
private DirectMessageConversationEntriesAdapter mAdapter;
private int mFirstVisibleItem;
private final Map<Long, Set<Long>> mUnreadCountsToRemove = Collections
.synchronizedMap(new HashMap<Long, Set<Long>>());
private final Map<Long, Set<Long>> mUnreadCountsToRemove = Collections
.synchronizedMap(new HashMap<Long, Set<Long>>());
private final Set<Integer> mReadPositions = Collections.synchronizedSet(new HashSet<Integer>());
private final Set<Integer> mReadPositions = Collections.synchronizedSet(new HashSet<Integer>());
private RemoveUnreadCountsTask mRemoveUnreadCountsTask;
private RemoveUnreadCountsTask mRemoveUnreadCountsTask;
@Override
public DirectMessageConversationEntriesAdapter getListAdapter() {
return (DirectMessageConversationEntriesAdapter) super.getListAdapter();
}
@Override
public DirectMessageConversationEntriesAdapter getListAdapter() {
return (DirectMessageConversationEntriesAdapter) super.getListAdapter();
}
public final Map<Long, Set<Long>> getUnreadCountsToRemove() {
return mUnreadCountsToRemove;
}
public final Map<Long, Set<Long>> getUnreadCountsToRemove() {
return mUnreadCountsToRemove;
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
super.onActivityCreated(savedInstanceState);
mMultiSelectManager = getMultiSelectManager();
mAdapter = new DirectMessageConversationEntriesAdapter(getActivity());
setListAdapter(mAdapter);
mListView = getListView();
if (!mPreferences.getBoolean(KEY_PLAIN_LIST_STYLE, false)) {
mListView.setDivider(null);
}
mListView.setSelector(android.R.color.transparent);
getLoaderManager().initLoader(0, null, this);
setListShown(false);
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
super.onActivityCreated(savedInstanceState);
mMultiSelectManager = getMultiSelectManager();
mAdapter = new DirectMessageConversationEntriesAdapter(getActivity());
setListAdapter(mAdapter);
mListView = getListView();
if (!mPreferences.getBoolean(KEY_COMPACT_CARDS, false)) {
mListView.setDivider(null);
}
mListView.setSelector(android.R.color.transparent);
getLoaderManager().initLoader(0, null, this);
setListShown(false);
}
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
final Uri uri = DirectMessages.ConversationEntries.CONTENT_URI;
final long account_id = getAccountId();
final long[] account_ids = account_id > 0 ? new long[] { account_id } : getActivatedAccountIds(getActivity());
final boolean no_account_selected = account_ids.length == 0;
setEmptyText(no_account_selected ? getString(R.string.no_account_selected) : null);
if (!no_account_selected) {
getListView().setEmptyView(null);
}
final Where account_where = Where.in(new Column(Statuses.ACCOUNT_ID), new RawItemArray(account_ids));
return new CursorLoader(getActivity(), uri, null, account_where.getSQL(), null, null);
}
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
final Uri uri = DirectMessages.ConversationEntries.CONTENT_URI;
final long account_id = getAccountId();
final long[] account_ids = account_id > 0 ? new long[]{account_id} : getActivatedAccountIds(getActivity());
final boolean no_account_selected = account_ids.length == 0;
setEmptyText(no_account_selected ? getString(R.string.no_account_selected) : null);
if (!no_account_selected) {
getListView().setEmptyView(null);
}
final Where account_where = Where.in(new Column(Statuses.ACCOUNT_ID), new RawItemArray(account_ids));
return new CursorLoader(getActivity(), uri, null, account_where.getSQL(), null, null);
}
@Override
public void onListItemClick(final ListView l, final View v, final int position, final long id) {
if (mMultiSelectManager.isActive()) return;
final int pos = position - l.getHeaderViewsCount();
final long conversationId = mAdapter.getConversationId(pos);
final long accountId = mAdapter.getAccountId(pos);
mReadPositions.add(pos);
removeUnreadCounts();
if (conversationId > 0 && accountId > 0) {
openDirectMessagesConversation(getActivity(), accountId, conversationId);
}
}
@Override
public void onListItemClick(final ListView l, final View v, final int position, final long id) {
if (mMultiSelectManager.isActive()) return;
final int pos = position - l.getHeaderViewsCount();
final long conversationId = mAdapter.getConversationId(pos);
final long accountId = mAdapter.getAccountId(pos);
mReadPositions.add(pos);
removeUnreadCounts();
if (conversationId > 0 && accountId > 0) {
openDirectMessagesConversation(getActivity(), accountId, conversationId);
}
}
@Override
public void onLoaderReset(final Loader<Cursor> loader) {
mAdapter.changeCursor(null);
}
@Override
public void onLoaderReset(final Loader<Cursor> loader) {
mAdapter.changeCursor(null);
}
@Override
public void onLoadFinished(final Loader<Cursor> loader, final Cursor cursor) {
if (getActivity() == null) return;
mFirstVisibleItem = -1;
mAdapter.changeCursor(cursor);
mAdapter.setShowAccountColor(getActivatedAccountIds(getActivity()).length > 1);
setListShown(true);
}
@Override
public void onLoadFinished(final Loader<Cursor> loader, final Cursor cursor) {
if (getActivity() == null) return;
mFirstVisibleItem = -1;
mAdapter.changeCursor(cursor);
mAdapter.setShowAccountColor(getActivatedAccountIds(getActivity()).length > 1);
setListShown(true);
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case MENU_COMPOSE: {
openDirectMessagesConversation(getActivity(), -1, -1);
break;
}
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case MENU_COMPOSE: {
openDirectMessagesConversation(getActivity(), -1, -1);
break;
}
}
return super.onOptionsItemSelected(item);
}
@Override
public void onRefreshFromEnd() {
if (mLoadMoreAutomatically) return;
loadMoreMessages();
}
@Override
public void onRefreshFromEnd() {
if (mLoadMoreAutomatically) return;
loadMoreMessages();
}
@Override
public void onRefreshFromStart() {
if (isRefreshing()) return;
new AsyncTask<Void, Void, long[][]>() {
@Override
public void onRefreshFromStart() {
if (isRefreshing()) return;
new AsyncTask<Void, Void, long[][]>() {
@Override
protected long[][] doInBackground(final Void... params) {
final long[][] result = new long[2][];
result[0] = getActivatedAccountIds(getActivity());
result[1] = getNewestMessageIdsFromDatabase(getActivity(), DirectMessages.Inbox.CONTENT_URI);
return result;
}
@Override
protected long[][] doInBackground(final Void... params) {
final long[][] result = new long[2][];
result[0] = getActivatedAccountIds(getActivity());
result[1] = getNewestMessageIdsFromDatabase(getActivity(), DirectMessages.Inbox.CONTENT_URI);
return result;
}
@Override
protected void onPostExecute(final long[][] result) {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter == null) return;
twitter.getReceivedDirectMessagesAsync(result[0], null, result[1]);
twitter.getSentDirectMessagesAsync(result[0], null, null);
}
@Override
protected void onPostExecute(final long[][] result) {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter == null) return;
twitter.getReceivedDirectMessagesAsync(result[0], null, result[1]);
twitter.getSentDirectMessagesAsync(result[0], null, null);
}
}.execute();
}
}.execute();
}
@Override
public void onResume() {
super.onResume();
mListView.setFastScrollEnabled(mPreferences.getBoolean(KEY_FAST_SCROLL_THUMB, false));
configBaseCardAdapter(getActivity(), mAdapter);
mLoadMoreAutomatically = mPreferences.getBoolean(KEY_LOAD_MORE_AUTOMATICALLY, false);
}
@Override
public void onResume() {
super.onResume();
mListView.setFastScrollEnabled(mPreferences.getBoolean(KEY_FAST_SCROLL_THUMB, false));
configBaseCardAdapter(getActivity(), mAdapter);
mLoadMoreAutomatically = mPreferences.getBoolean(KEY_LOAD_MORE_AUTOMATICALLY, false);
}
@Override
public void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount,
final int totalItemCount) {
super.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
addReadPosition(firstVisibleItem);
}
@Override
public void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount,
final int totalItemCount) {
super.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
addReadPosition(firstVisibleItem);
}
@Override
public void onScrollStateChanged(final AbsListView view, final int scrollState) {
switch (scrollState) {
case SCROLL_STATE_FLING:
case SCROLL_STATE_TOUCH_SCROLL: {
break;
}
case SCROLL_STATE_IDLE: {
for (int i = mListView.getFirstVisiblePosition(), j = mListView.getLastVisiblePosition(); i < j; i++) {
mReadPositions.add(i);
}
removeUnreadCounts();
break;
}
}
}
@Override
public void onScrollStateChanged(final AbsListView view, final int scrollState) {
switch (scrollState) {
case SCROLL_STATE_FLING:
case SCROLL_STATE_TOUCH_SCROLL: {
break;
}
case SCROLL_STATE_IDLE: {
for (int i = mListView.getFirstVisiblePosition(), j = mListView.getLastVisiblePosition(); i < j; i++) {
mReadPositions.add(i);
}
removeUnreadCounts();
break;
}
}
}
@Override
public void onStart() {
super.onStart();
final ContentResolver resolver = getContentResolver();
resolver.registerContentObserver(Accounts.CONTENT_URI, true, mReloadContentObserver);
final IntentFilter filter = new IntentFilter();
filter.addAction(BROADCAST_TASK_STATE_CHANGED);
registerReceiver(mStatusReceiver, filter);
}
@Override
public void onStart() {
super.onStart();
final ContentResolver resolver = getContentResolver();
resolver.registerContentObserver(Accounts.CONTENT_URI, true, mReloadContentObserver);
final IntentFilter filter = new IntentFilter();
filter.addAction(BROADCAST_TASK_STATE_CHANGED);
registerReceiver(mStatusReceiver, filter);
}
@Override
public void onStop() {
unregisterReceiver(mStatusReceiver);
final ContentResolver resolver = getContentResolver();
resolver.unregisterContentObserver(mReloadContentObserver);
super.onStop();
}
@Override
public void onStop() {
unregisterReceiver(mStatusReceiver);
final ContentResolver resolver = getContentResolver();
resolver.unregisterContentObserver(mReloadContentObserver);
super.onStop();
}
@Override
public boolean scrollToStart() {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
final int tabPosition = getTabPosition();
if (twitter != null && tabPosition >= 0) {
twitter.clearUnreadCountAsync(tabPosition);
}
return super.scrollToStart();
}
@Override
public boolean scrollToStart() {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
final int tabPosition = getTabPosition();
if (twitter != null && tabPosition >= 0) {
twitter.clearUnreadCountAsync(tabPosition);
}
return super.scrollToStart();
}
@Override
public void setUserVisibleHint(final boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
updateRefreshState();
}
}
@Override
public void setUserVisibleHint(final boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
updateRefreshState();
}
}
protected long getAccountId() {
final Bundle args = getArguments();
return args != null ? args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
}
protected long getAccountId() {
final Bundle args = getArguments();
return args != null ? args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
}
@Override
protected void onListTouched() {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter != null) {
twitter.clearNotificationAsync(NOTIFICATION_ID_DIRECT_MESSAGES, getAccountId());
}
}
@Override
protected void onListTouched() {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter != null) {
twitter.clearNotificationAsync(NOTIFICATION_ID_DIRECT_MESSAGES, getAccountId());
}
}
@Override
protected void onReachedBottom() {
if (!mLoadMoreAutomatically) return;
loadMoreMessages();
}
@Override
protected void onReachedBottom() {
if (!mLoadMoreAutomatically) return;
loadMoreMessages();
}
protected void updateRefreshState() {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter == null || !getUserVisibleHint()) return;
setRefreshing(twitter.isReceivedDirectMessagesRefreshing() || twitter.isSentDirectMessagesRefreshing());
}
protected void updateRefreshState() {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter == null || !getUserVisibleHint()) return;
setRefreshing(twitter.isReceivedDirectMessagesRefreshing() || twitter.isSentDirectMessagesRefreshing());
}
private void addReadPosition(final int firstVisibleItem) {
if (mFirstVisibleItem != firstVisibleItem) {
mReadPositions.add(firstVisibleItem);
}
mFirstVisibleItem = firstVisibleItem;
}
private void addReadPosition(final int firstVisibleItem) {
if (mFirstVisibleItem != firstVisibleItem) {
mReadPositions.add(firstVisibleItem);
}
mFirstVisibleItem = firstVisibleItem;
}
private void addUnreadCountsToRemove(final long account_id, final long id) {
if (mUnreadCountsToRemove.containsKey(account_id)) {
final Set<Long> counts = mUnreadCountsToRemove.get(account_id);
counts.add(id);
} else {
final Set<Long> counts = new HashSet<Long>();
counts.add(id);
mUnreadCountsToRemove.put(account_id, counts);
}
}
private void addUnreadCountsToRemove(final long account_id, final long id) {
if (mUnreadCountsToRemove.containsKey(account_id)) {
final Set<Long> counts = mUnreadCountsToRemove.get(account_id);
counts.add(id);
} else {
final Set<Long> counts = new HashSet<Long>();
counts.add(id);
mUnreadCountsToRemove.put(account_id, counts);
}
}
private void loadMoreMessages() {
if (isRefreshing()) return;
new AsyncTask<Void, Void, long[][]>() {
private void loadMoreMessages() {
if (isRefreshing()) return;
new AsyncTask<Void, Void, long[][]>() {
@Override
protected long[][] doInBackground(final Void... params) {
final long[][] result = new long[3][];
result[0] = getActivatedAccountIds(getActivity());
result[1] = getOldestMessageIdsFromDatabase(getActivity(), DirectMessages.Inbox.CONTENT_URI);
result[2] = getOldestMessageIdsFromDatabase(getActivity(), DirectMessages.Outbox.CONTENT_URI);
return result;
}
@Override
protected long[][] doInBackground(final Void... params) {
final long[][] result = new long[3][];
result[0] = getActivatedAccountIds(getActivity());
result[1] = getOldestMessageIdsFromDatabase(getActivity(), DirectMessages.Inbox.CONTENT_URI);
result[2] = getOldestMessageIdsFromDatabase(getActivity(), DirectMessages.Outbox.CONTENT_URI);
return result;
}
@Override
protected void onPostExecute(final long[][] result) {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter == null) return;
twitter.getReceivedDirectMessagesAsync(result[0], result[1], null);
twitter.getSentDirectMessagesAsync(result[0], result[2], null);
}
@Override
protected void onPostExecute(final long[][] result) {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter == null) return;
twitter.getReceivedDirectMessagesAsync(result[0], result[1], null);
twitter.getSentDirectMessagesAsync(result[0], result[2], null);
}
}.execute();
}
}.execute();
}
private void removeUnreadCounts() {
if (mRemoveUnreadCountsTask != null && mRemoveUnreadCountsTask.getStatus() == AsyncTask.Status.RUNNING) return;
mRemoveUnreadCountsTask = new RemoveUnreadCountsTask(mReadPositions, this);
mRemoveUnreadCountsTask.execute();
}
private void removeUnreadCounts() {
if (mRemoveUnreadCountsTask != null && mRemoveUnreadCountsTask.getStatus() == AsyncTask.Status.RUNNING)
return;
mRemoveUnreadCountsTask = new RemoveUnreadCountsTask(mReadPositions, this);
mRemoveUnreadCountsTask.execute();
}
static class RemoveUnreadCountsTask extends AsyncTask<Void, Void, Void> {
private final Set<Integer> read_positions;
private final DirectMessageConversationEntriesAdapter adapter;
private final DirectMessagesFragment fragment;
static class RemoveUnreadCountsTask extends AsyncTask<Void, Void, Void> {
private final Set<Integer> read_positions;
private final DirectMessageConversationEntriesAdapter adapter;
private final DirectMessagesFragment fragment;
RemoveUnreadCountsTask(final Set<Integer> read_positions, final DirectMessagesFragment fragment) {
this.read_positions = Collections.synchronizedSet(new HashSet<Integer>(read_positions));
this.fragment = fragment;
adapter = fragment.getListAdapter();
}
RemoveUnreadCountsTask(final Set<Integer> read_positions, final DirectMessagesFragment fragment) {
this.read_positions = Collections.synchronizedSet(new HashSet<Integer>(read_positions));
this.fragment = fragment;
adapter = fragment.getListAdapter();
}
@Override
protected Void doInBackground(final Void... params) {
for (final int pos : read_positions) {
final long id = adapter.getConversationId(pos), account_id = adapter.getAccountId(pos);
fragment.addUnreadCountsToRemove(account_id, id);
}
return null;
}
@Override
protected Void doInBackground(final Void... params) {
for (final int pos : read_positions) {
final long id = adapter.getConversationId(pos), account_id = adapter.getAccountId(pos);
fragment.addUnreadCountsToRemove(account_id, id);
}
return null;
}
@Override
protected void onPostExecute(final Void result) {
final AsyncTwitterWrapper twitter = fragment.getTwitterWrapper();
if (twitter != null) {
twitter.removeUnreadCountsAsync(fragment.getTabPosition(), fragment.getUnreadCountsToRemove());
}
}
@Override
protected void onPostExecute(final Void result) {
final AsyncTwitterWrapper twitter = fragment.getTwitterWrapper();
if (twitter != null) {
twitter.removeUnreadCountsAsync(fragment.getTabPosition(), fragment.getUnreadCountsToRemove());
}
}
}
}
}

View File

@ -1,98 +1,51 @@
/*
* Twidere - Twitter client for Android
*
* 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.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import org.mariotaku.twidere.adapter.CursorStatusesListAdapter;
import org.mariotaku.twidere.provider.TweetStore.Statuses;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
public class HomeTimelineFragment extends CursorStatusesListFragment {
private final BroadcastReceiver mStatusReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
if (getActivity() == null || !isAdded() || isDetached()) return;
final String action = intent.getAction();
if (BROADCAST_HOME_TIMELINE_REFRESHED.equals(action)) {
setRefreshComplete();
} else if (BROADCAST_TASK_STATE_CHANGED.equals(action)) {
updateRefreshState();
}
}
};
/**
* Created by mariotaku on 14/12/3.
*/
public class HomeTimelineFragment extends CursorStatusesFragment {
@Override
public int getStatuses(final long[] accountIds, final long[] maxIds, final long[] sinceIds) {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter == null) return 0;
if (maxIds == null) return twitter.refreshAll(accountIds);
return twitter.getHomeTimelineAsync(accountIds, maxIds, sinceIds);
public int getStatuses(long[] accountIds, long[] maxIds, long[] sinceIds) {
return 0;
}
@Override
public void onStart() {
super.onStart();
final IntentFilter filter = new IntentFilter(BROADCAST_HOME_TIMELINE_REFRESHED);
filter.addAction(BROADCAST_TASK_STATE_CHANGED);
registerReceiver(mStatusReceiver, filter);
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
final Context context = getActivity();
final Uri uri = Statuses.CONTENT_URI;
final SharedPreferences preferences = getSharedPreferences();
final boolean sortById = preferences.getBoolean(KEY_SORT_TIMELINE_BY_ID, false);
final String sortOrder = sortById ? Statuses.SORT_ORDER_STATUS_ID_DESC : Statuses.SORT_ORDER_TIMESTAMP_DESC;
return new CursorLoader(context, uri, CursorStatusesListAdapter.CURSOR_COLS, null, null, sortOrder);
}
@Override
public void onStop() {
unregisterReceiver(mStatusReceiver);
super.onStop();
}
@Override
protected Uri getContentUri() {
return Statuses.CONTENT_URI;
}
@Override
protected int getNotificationType() {
return NOTIFICATION_ID_HOME_TIMELINE;
}
@Override
protected String getPositionKey() {
return "home_timeline" + getTabPosition();
}
@Override
protected boolean isFiltersEnabled() {
final SharedPreferences pref = getSharedPreferences();
return pref != null && pref.getBoolean(KEY_FILTERS_IN_HOME_TIMELINE, true);
}
@Override
protected void updateRefreshState() {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter == null || !getUserVisibleHint() || getActivity() == null) return;
setRefreshing(twitter.isHomeTimelineRefreshing());
}
}

View File

@ -0,0 +1,98 @@
/*
* 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.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.Uri;
import org.mariotaku.twidere.provider.TweetStore.Statuses;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
public class HomeTimelineListFragment extends CursorStatusesListFragment {
private final BroadcastReceiver mStatusReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
if (getActivity() == null || !isAdded() || isDetached()) return;
final String action = intent.getAction();
if (BROADCAST_HOME_TIMELINE_REFRESHED.equals(action)) {
setRefreshComplete();
} else if (BROADCAST_TASK_STATE_CHANGED.equals(action)) {
updateRefreshState();
}
}
};
@Override
public int getStatuses(final long[] accountIds, final long[] maxIds, final long[] sinceIds) {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter == null) return 0;
if (maxIds == null) return twitter.refreshAll(accountIds);
return twitter.getHomeTimelineAsync(accountIds, maxIds, sinceIds);
}
@Override
public void onStart() {
super.onStart();
final IntentFilter filter = new IntentFilter(BROADCAST_HOME_TIMELINE_REFRESHED);
filter.addAction(BROADCAST_TASK_STATE_CHANGED);
registerReceiver(mStatusReceiver, filter);
}
@Override
public void onStop() {
unregisterReceiver(mStatusReceiver);
super.onStop();
}
@Override
protected Uri getContentUri() {
return Statuses.CONTENT_URI;
}
@Override
protected int getNotificationType() {
return NOTIFICATION_ID_HOME_TIMELINE;
}
@Override
protected String getPositionKey() {
return "home_timeline" + getTabPosition();
}
@Override
protected boolean isFiltersEnabled() {
final SharedPreferences pref = getSharedPreferences();
return pref != null && pref.getBoolean(KEY_FILTERS_IN_HOME_TIMELINE, true);
}
@Override
protected void updateRefreshState() {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter == null || !getUserVisibleHint() || getActivity() == null) return;
setRefreshing(twitter.isHomeTimelineRefreshing());
}
}

View File

@ -0,0 +1,53 @@
/*
* 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 org.mariotaku.twidere.adapter.ParcelableStatusesAdapter;
import org.mariotaku.twidere.model.ParcelableStatus;
import java.util.List;
/**
* Created by mariotaku on 14/12/3.
*/
public abstract class ParcelableStatusesFragment extends AbsStatusesFragment<List<ParcelableStatus>> {
@Override
protected ParcelableStatusesAdapter onCreateAdapter(final Context context, final boolean compact) {
return new ParcelableStatusesAdapter(context, compact);
}
@Override
public int getStatuses(long[] accountIds, final long[] maxIds, final long[] sinceIds) {
final Bundle args = new Bundle(getArguments());
if (maxIds != null) {
args.putLong(EXTRA_MAX_ID, maxIds[0]);
}
if (sinceIds != null) {
args.putLong(EXTRA_SINCE_ID, sinceIds[0]);
}
getLoaderManager().restartLoader(0, args, this);
return -1;
}
}

View File

@ -208,8 +208,8 @@ public abstract class ParcelableStatusesListFragment extends BaseStatusesListFra
}
@Override
protected ParcelableStatusesListAdapter newAdapterInstance(final boolean compact, final boolean plain) {
return new ParcelableStatusesListAdapter(getActivity(), compact, plain);
protected ParcelableStatusesListAdapter newAdapterInstance(final boolean compact) {
return new ParcelableStatusesListAdapter(getActivity(), compact);
}
protected abstract Loader<List<ParcelableStatus>> newLoaderInstance(Context context, Bundle args);

View File

@ -43,6 +43,7 @@ import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.support.v4.util.Pair;
import android.support.v4.view.ViewCompat;
import android.text.Html;
import android.text.SpannableString;
import android.text.TextUtils;
@ -140,6 +141,8 @@ import static org.mariotaku.twidere.util.Utils.startStatusShareChooser;
public class StatusFragment extends ParcelableStatusesListFragment implements OnClickListener,
OnMediaClickListener, OnSharedPreferenceChangeListener, ActionMode.Callback {
public static final String TRANSITION_NAME_CARD = "card";
private static final int LOADER_ID_STATUS = 1;
private static final int LOADER_ID_FOLLOW = 2;
private static final int LOADER_ID_LOCATION = 3;
@ -614,7 +617,7 @@ public class StatusFragment extends ParcelableStatusesListFragment implements On
mLoadImagesIndicator = mHeaderView.findViewById(R.id.load_images);
mRetryButton = (Button) view.findViewById(R.id.retry);
final View cardView = mHeaderView.findViewById(R.id.card);
ThemeUtils.applyThemeAlphaToDrawable(cardView.getContext(), cardView.getBackground());
ViewCompat.setTransitionName(cardView, TRANSITION_NAME_CARD);
return view;
}

View File

@ -1,118 +1,51 @@
/*
* Twidere - Twitter client for Android
*
* 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 static org.mariotaku.twidere.util.Utils.getAccountId;
import static org.mariotaku.twidere.util.Utils.isSameAccount;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.Loader;
import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter;
import org.mariotaku.twidere.loader.support.UserFavoritesLoader;
import org.mariotaku.twidere.model.ParcelableStatus;
import java.util.List;
public class UserFavoritesFragment extends ParcelableStatusesListFragment {
/**
* Created by mariotaku on 14/12/2.
*/
public class UserFavoritesFragment extends ParcelableStatusesFragment {
private long mUserId;
private String mUserScreenName;
private final BroadcastReceiver mStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
if (getActivity() == null || !isAdded() || isDetached()) return;
final String action = intent.getAction();
if (BROADCAST_FAVORITE_CHANGED.equals(action)) {
final ParcelableStatus status = intent.getParcelableExtra(EXTRA_STATUS);
if (status == null) return;
if ((isSameAccount(context, status.account_id, mUserId) || isSameAccount(context, status.account_id,
mUserScreenName)) && status.id > 0 && !intent.getBooleanExtra(EXTRA_FAVORITED, true)) {
deleteStatus(status.id);
}
}
}
};
@Override
public Loader<List<ParcelableStatus>> newLoaderInstance(final Context context, final Bundle args) {
if (args == null) return null;
final long account_id = args.getLong(EXTRA_ACCOUNT_ID);
final long user_id = args.getLong(EXTRA_USER_ID, -1);
final long max_id = args.getLong(EXTRA_MAX_ID, -1);
final long since_id = args.getLong(EXTRA_SINCE_ID, -1);
final String screen_name = args.getString(EXTRA_SCREEN_NAME);
final int tab_position = args.getInt(EXTRA_TAB_POSITION, -1);
mUserId = user_id;
mUserScreenName = screen_name;
return new UserFavoritesLoader(getActivity(), account_id, user_id, screen_name, max_id, since_id, getData(),
getSavedStatusesFileArgs(), tab_position);
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final Bundle args = getArguments();
final long account_id = args != null ? args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
final long user_id = args != null ? args.getLong(EXTRA_USER_ID, -1) : -1;
final String screen_name = args != null ? args.getString(EXTRA_SCREEN_NAME) : null;
final boolean is_my_timeline = user_id > 0 ? account_id == user_id : account_id == getAccountId(getActivity(),
screen_name);
final IStatusesListAdapter<List<ParcelableStatus>> adapter = getListAdapter();
adapter.setFavoritesHightlightDisabled(is_my_timeline);
adapter.setFiltersEnabled(false);
}
@Override
public void onStart() {
super.onStart();
final IntentFilter filter = new IntentFilter(BROADCAST_FAVORITE_CHANGED);
registerReceiver(mStateReceiver, filter);
}
@Override
public void onStop() {
unregisterReceiver(mStateReceiver);
super.onStop();
}
@Override
protected String[] getSavedStatusesFileArgs() {
final Bundle args = getArguments();
if (args == null) return null;
final long account_id = args.getLong(EXTRA_ACCOUNT_ID, -1);
final long user_id = args.getLong(EXTRA_USER_ID, -1);
final String screen_name = args.getString(EXTRA_SCREEN_NAME);
return new String[] { AUTHORITY_USER_FAVORITES, "account" + account_id, "user" + user_id, "name" + screen_name };
}
@Override
protected boolean shouldShowAccountColor() {
return false;
}
@Override
public Loader<List<ParcelableStatus>> onCreateLoader(int id, Bundle args) {
setRefreshing(true);
final List<ParcelableStatus> data = getAdapterData();
final Context context = getActivity();
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
final long maxId = args.getLong(EXTRA_MAX_ID, -1);
final long sinceId = args.getLong(EXTRA_SINCE_ID, -1);
final long userId = args.getLong(EXTRA_USER_ID, -1);
final String screenName = args.getString(EXTRA_SCREEN_NAME);
final int tabPosition = args.getInt(EXTRA_TAB_POSITION, -1);
return new UserFavoritesLoader(context, accountId, userId, screenName, maxId, sinceId, data,
null, tabPosition);
}
}

View File

@ -0,0 +1,118 @@
/*
* 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 static org.mariotaku.twidere.util.Utils.getAccountId;
import static org.mariotaku.twidere.util.Utils.isSameAccount;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.Loader;
import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter;
import org.mariotaku.twidere.loader.support.UserFavoritesLoader;
import org.mariotaku.twidere.model.ParcelableStatus;
import java.util.List;
public class UserFavoritesFragmentOld extends ParcelableStatusesListFragment {
private long mUserId;
private String mUserScreenName;
private final BroadcastReceiver mStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
if (getActivity() == null || !isAdded() || isDetached()) return;
final String action = intent.getAction();
if (BROADCAST_FAVORITE_CHANGED.equals(action)) {
final ParcelableStatus status = intent.getParcelableExtra(EXTRA_STATUS);
if (status == null) return;
if ((isSameAccount(context, status.account_id, mUserId) || isSameAccount(context, status.account_id,
mUserScreenName)) && status.id > 0 && !intent.getBooleanExtra(EXTRA_FAVORITED, true)) {
deleteStatus(status.id);
}
}
}
};
@Override
public Loader<List<ParcelableStatus>> newLoaderInstance(final Context context, final Bundle args) {
if (args == null) return null;
final long account_id = args.getLong(EXTRA_ACCOUNT_ID);
final long user_id = args.getLong(EXTRA_USER_ID, -1);
final long max_id = args.getLong(EXTRA_MAX_ID, -1);
final long since_id = args.getLong(EXTRA_SINCE_ID, -1);
final String screen_name = args.getString(EXTRA_SCREEN_NAME);
final int tab_position = args.getInt(EXTRA_TAB_POSITION, -1);
mUserId = user_id;
mUserScreenName = screen_name;
return new UserFavoritesLoader(getActivity(), account_id, user_id, screen_name, max_id, since_id, getData(),
getSavedStatusesFileArgs(), tab_position);
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final Bundle args = getArguments();
final long account_id = args != null ? args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
final long user_id = args != null ? args.getLong(EXTRA_USER_ID, -1) : -1;
final String screen_name = args != null ? args.getString(EXTRA_SCREEN_NAME) : null;
final boolean is_my_timeline = user_id > 0 ? account_id == user_id : account_id == getAccountId(getActivity(),
screen_name);
final IStatusesListAdapter<List<ParcelableStatus>> adapter = getListAdapter();
adapter.setFavoritesHightlightDisabled(is_my_timeline);
adapter.setFiltersEnabled(false);
}
@Override
public void onStart() {
super.onStart();
final IntentFilter filter = new IntentFilter(BROADCAST_FAVORITE_CHANGED);
registerReceiver(mStateReceiver, filter);
}
@Override
public void onStop() {
unregisterReceiver(mStateReceiver);
super.onStop();
}
@Override
protected String[] getSavedStatusesFileArgs() {
final Bundle args = getArguments();
if (args == null) return null;
final long account_id = args.getLong(EXTRA_ACCOUNT_ID, -1);
final long user_id = args.getLong(EXTRA_USER_ID, -1);
final String screen_name = args.getString(EXTRA_SCREEN_NAME);
return new String[] { AUTHORITY_USER_FAVORITES, "account" + account_id, "user" + user_id, "name" + screen_name };
}
@Override
protected boolean shouldShowAccountColor() {
return false;
}
}

View File

@ -108,11 +108,11 @@ import org.mariotaku.twidere.util.TwidereLinkify.OnLinkClickListener;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.menu.TwidereMenuInfo;
import org.mariotaku.twidere.view.CircularImageView;
import org.mariotaku.twidere.view.ColorLabelLinearLayout;
import org.mariotaku.twidere.view.HeaderDrawerLayout;
import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback;
import org.mariotaku.twidere.view.ProfileBannerImageView;
import org.mariotaku.twidere.view.TintedStatusFrameLayout;
import org.mariotaku.twidere.view.iface.IColorLabelView;
import org.mariotaku.twidere.view.iface.IExtendedView.OnSizeChangedListener;
import java.util.Locale;
@ -171,10 +171,9 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
private View mDescriptionContainer, mLocationContainer, mURLContainer, mListedContainer, mFollowersContainer,
mFriendsContainer;
private Button mRetryButton;
private ColorLabelLinearLayout mProfileNameContainer;
private IColorLabelView mProfileNameContainer;
private View mProgressContainer, mErrorRetryContainer;
private View mFollowingYouIndicator;
private View mMainContent;
private View mCardContent;
private View mProfileBannerSpace;
private TintedStatusFrameLayout mTintedStatusContent;
private HeaderDrawerLayout mHeaderDrawerLayout;
@ -182,6 +181,8 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
private PagerSlidingTabStrip mPagerIndicator;
private CardView mCardView;
private View mUuckyFooter;
private View mProfileBannerContainer;
private Button mFollowButton;
private SupportTabsAdapter mPagerAdapter;
@ -233,8 +234,12 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
@Override
public Loader<SingleResponse<ParcelableUser>> onCreateLoader(final int id, final Bundle args) {
if (mUser == null) {
mMainContent.setVisibility(View.VISIBLE);
final boolean omitIntentExtra = args.getBoolean(EXTRA_OMIT_INTENT_EXTRA, true);
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
final long userId = args.getLong(EXTRA_USER_ID, -1);
final String screenName = args.getString(EXTRA_SCREEN_NAME);
if (mUser == null && (!omitIntentExtra || !args.containsKey(EXTRA_USER))) {
mCardContent.setVisibility(View.GONE);
mErrorRetryContainer.setVisibility(View.GONE);
mProgressContainer.setVisibility(View.VISIBLE);
mErrorMessageView.setText(null);
@ -243,10 +248,6 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
}
setProgressBarIndeterminateVisibility(true);
final ParcelableUser user = mUser;
final boolean omitIntentExtra = args.getBoolean(EXTRA_OMIT_INTENT_EXTRA, true);
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
final long userId = args.getLong(EXTRA_USER_ID, -1);
final String screenName = args.getString(EXTRA_SCREEN_NAME);
return new ParcelableUserLoader(getActivity(), accountId, userId, screenName, getArguments(),
omitIntentExtra, user == null || !user.is_cache && userId != user.id);
}
@ -262,7 +263,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
if (getActivity() == null) return;
if (data.getData() != null && data.getData().id > 0) {
final ParcelableUser user = data.getData();
mMainContent.setVisibility(View.VISIBLE);
mCardContent.setVisibility(View.VISIBLE);
mErrorRetryContainer.setVisibility(View.GONE);
mProgressContainer.setVisibility(View.GONE);
setListShown(true);
@ -276,7 +277,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
getLoaderManager().restartLoader(LOADER_ID_USER, args, this);
}
} else if (mUser != null && mUser.is_cache) {
mMainContent.setVisibility(View.VISIBLE);
mCardContent.setVisibility(View.VISIBLE);
mErrorRetryContainer.setVisibility(View.GONE);
mProgressContainer.setVisibility(View.GONE);
setListShown(true);
@ -286,7 +287,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
mErrorMessageView.setText(getErrorMessage(getActivity(), data.getException()));
mErrorMessageView.setVisibility(View.VISIBLE);
}
mMainContent.setVisibility(View.GONE);
mCardContent.setVisibility(View.GONE);
mErrorRetryContainer.setVisibility(View.VISIBLE);
mProgressContainer.setVisibility(View.GONE);
}
@ -299,6 +300,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
@Override
public Loader<SingleResponse<Relationship>> onCreateLoader(final int id, final Bundle args) {
invalidateOptionsMenu();
mFollowButton.setVisibility(View.GONE);
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
final long userId = args.getLong(EXTRA_USER_ID, -1);
return new FriendshipLoader(getActivity(), accountId, userId);
@ -317,10 +319,18 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
final Relationship relationship = mRelationship = data.getData();
if (user == null) return;
invalidateOptionsMenu();
if (relationship != null) {
final boolean isMyself = user.account_id == user.id;
final boolean isFollowingYou = relationship.isTargetFollowingSource();
mFollowingYouIndicator.setVisibility(!isMyself && isFollowingYou ? View.VISIBLE : View.GONE);
final boolean isMyself = user.account_id == user.id;
if (isMyself) {
mFollowButton.setText(R.string.edit);
mFollowButton.setVisibility(View.VISIBLE);
} else if (relationship != null) {
if (relationship.isSourceBlockingTarget()) {
mFollowButton.setText(R.string.unblock);
} else if (relationship.isSourceFollowingTarget()) {
mFollowButton.setText(R.string.unfollow);
} else {
mFollowButton.setText(R.string.follow);
}
final ContentResolver resolver = getContentResolver();
final String where = Where.equals(CachedUsers.USER_ID, user.id).getSQL();
resolver.delete(CachedUsers.CONTENT_URI, where, null);
@ -332,8 +342,11 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
resolver.insert(CachedUsers.CONTENT_URI, cachedValues);
}
}
mFollowButton.setVisibility(View.VISIBLE);
} else {
mFollowingYouIndicator.setVisibility(View.GONE);
mFollowButton.setText(null);
mFollowButton.setVisibility(View.GONE);
// mFollowingYouIndicator.setVisibility(View.GONE);
}
}
@ -348,6 +361,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
lm.destroyLoader(LOADER_ID_USER);
lm.destroyLoader(LOADER_ID_FRIENDSHIP);
final boolean userIsMe = user.account_id == user.id;
mCardContent.setVisibility(View.VISIBLE);
mErrorRetryContainer.setVisibility(View.GONE);
mProgressContainer.setVisibility(View.GONE);
mUser = user;
@ -466,6 +480,14 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
}
}
@Override
public boolean shouldLayoutHeaderBottom() {
final HeaderDrawerLayout drawer = mHeaderDrawerLayout;
final CardView card = mCardView;
if (drawer == null || card == null) return false;
return card.getTop() + drawer.getHeaderTop() - drawer.getPaddingTop() <= 0;
}
@Override
public Fragment getCurrentVisibleFragment() {
return mCurrentVisibleFragment;
@ -497,7 +519,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
lm.destroyLoader(LOADER_ID_USER);
lm.destroyLoader(LOADER_ID_FRIENDSHIP);
if (!isMyAccount(getActivity(), accountId)) {
mMainContent.setVisibility(View.GONE);
mCardContent.setVisibility(View.GONE);
mErrorRetryContainer.setVisibility(View.GONE);
return;
}
@ -513,7 +535,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
lm.restartLoader(LOADER_ID_USER, args, mUserInfoLoaderCallbacks);
}
if (accountId == -1 || userId == -1 && screenName == null) {
mMainContent.setVisibility(View.GONE);
mCardContent.setVisibility(View.GONE);
mErrorRetryContainer.setVisibility(View.GONE);
return;
}
@ -598,6 +620,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
mPagerAdapter = new SupportTabsAdapter(activity, getChildFragmentManager());
mViewPager.setOffscreenPageLimit(3);
mViewPager.setAdapter(mPagerAdapter);
mPagerIndicator.setViewPager(mViewPager);
@ -766,7 +789,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
public void onGenerated(Palette palette) {
final ParcelableUser user = mUser;
if (user == null) return;
final int color = palette.getVibrantColor(0);
final int color = palette.getDarkVibrantColor(user.link_color);
setupUserColorActionBar(color);
}
});
@ -804,17 +827,17 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
@Override
public void onViewCreated(final View view, final Bundle savedInstanceState) {
final Context context = view.getContext();
super.onViewCreated(view, savedInstanceState);
mMainContent = view.findViewById(R.id.details_container);
mHeaderDrawerLayout = (HeaderDrawerLayout) view.findViewById(R.id.user_profile_drawer);
mErrorRetryContainer = view.findViewById(R.id.error_retry_container);
mProgressContainer = view.findViewById(R.id.progress_container);
mRetryButton = (Button) view.findViewById(R.id.retry);
mErrorMessageView = (TextView) view.findViewById(R.id.error_message);
mProfileBannerView = (ProfileBannerImageView) view.findViewById(R.id.profile_banner);
final View headerView = mHeaderDrawerLayout.getHeader();
final View contentView = mHeaderDrawerLayout.getContent();
super.onViewCreated(view, savedInstanceState);
mCardContent = headerView.findViewById(R.id.card_content);
mErrorRetryContainer = headerView.findViewById(R.id.error_retry_container);
mProgressContainer = headerView.findViewById(R.id.progress_container);
mRetryButton = (Button) headerView.findViewById(R.id.retry);
mErrorMessageView = (TextView) headerView.findViewById(R.id.error_message);
mProfileBannerView = (ProfileBannerImageView) view.findViewById(R.id.profile_banner);
mProfileBannerContainer = view.findViewById(R.id.profile_banner_container);
mCardView = (CardView) headerView.findViewById(R.id.card);
mNameView = (TextView) headerView.findViewById(R.id.name);
mScreenNameView = (TextView) headerView.findViewById(R.id.screen_name);
@ -828,37 +851,24 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
mFollowersCount = (TextView) headerView.findViewById(R.id.followers_count);
mFriendsContainer = headerView.findViewById(R.id.friends_container);
mFriendsCount = (TextView) headerView.findViewById(R.id.friends_count);
mProfileNameContainer = (ColorLabelLinearLayout) headerView.findViewById(R.id.profile_name_container);
mProfileNameContainer = (IColorLabelView) headerView.findViewById(R.id.profile_name_container);
mProfileImageView = (CircularImageView) headerView.findViewById(R.id.profile_image);
mProfileTypeView = (ImageView) headerView.findViewById(R.id.profile_type);
mDescriptionContainer = headerView.findViewById(R.id.description_container);
mLocationContainer = headerView.findViewById(R.id.location_container);
mURLContainer = headerView.findViewById(R.id.url_container);
mFollowingYouIndicator = headerView.findViewById(R.id.following_you_indicator);
mProfileBannerSpace = headerView.findViewById(R.id.profile_banner_space);
mViewPager = (ViewPager) contentView.findViewById(R.id.view_pager);
mPagerIndicator = (PagerSlidingTabStrip) contentView.findViewById(R.id.view_pager_tabs);
mFollowButton = (Button) headerView.findViewById(R.id.follow);
mUuckyFooter = headerView.findViewById(R.id.uucky_footer);
}
@Override
protected void fitSystemWindows(Rect insets) {
super.fitSystemWindows(insets);
final View view = getView();
if (view != null) {
final View progress = view.findViewById(R.id.progress_container);
progress.setPadding(insets.left, insets.top, insets.right, insets.bottom);
}
mErrorRetryContainer.setPadding(insets.left, insets.top, insets.right, insets.bottom);
mHeaderDrawerLayout.setPadding(insets.left, insets.top, insets.right, insets.bottom);
mHeaderDrawerLayout.setClipToPadding(ThemeUtils.isTransparentBackground(getActivity()));
final int bannerHeight = mProfileBannerView.getHeight();
if (bannerHeight != 0) {
final ViewGroup.LayoutParams params = mProfileBannerSpace.getLayoutParams();
params.height = bannerHeight - insets.top;
mProfileBannerSpace.setLayoutParams(params);
mProfileBannerSpace.requestLayout();
}
}
public void setListShown(boolean shown) {
@ -1147,13 +1157,13 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
private void updateScrollOffset(int offset) {
final View space = mProfileBannerSpace;
if (space == null) return;
final ProfileBannerImageView profileBannerView = mProfileBannerView;
final View profileBannerContainer = mProfileBannerContainer;
final int spaceHeight = space.getHeight();
final float factor = MathUtils.clamp(offset / (float) spaceHeight, 0, 1);
final ProfileBannerImageView profileBannerView = mProfileBannerView;
profileBannerView.setAlpha(1.0f - factor / 8f);
profileBannerView.setTranslationY(Math.min(offset, spaceHeight) / -2);
profileBannerView.setBottomClip(Math.min(offset, spaceHeight));
profileBannerContainer.setTranslationY(-offset);
profileBannerView.setTranslationY(Math.min(offset, spaceHeight) / 2);
if (mActionBarBackground != null && mTintedStatusContent != null) {
mActionBarBackground.setFactor(factor);

View File

@ -451,6 +451,11 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList
}
@Override
public boolean shouldLayoutHeaderBottom() {
return false;
}
@Override
public boolean canScroll(float dy) {
return false;

View File

@ -15,7 +15,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.mariotaku.twidere.R;
@ -25,6 +24,8 @@ import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.ImageLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.SimpleDrawerCallback;
import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback;
import org.mariotaku.twidere.view.MediaSizeImageView;
import java.util.List;
@ -33,12 +34,50 @@ import java.util.List;
* Created by mariotaku on 14/11/5.
*/
public class UserMediaTimelineFragment extends BaseSupportFragment
implements LoaderCallbacks<List<ParcelableStatus>> {
implements LoaderCallbacks<List<ParcelableStatus>>, DrawerCallback {
private View mProgressContainer;
private RecyclerView mRecyclerView;
private ProgressBar mProgress;
private MediaTimelineAdapter mAdapter;
@Override
public void fling(float velocity) {
mDrawerCallback.fling(velocity);
}
@Override
public void scrollBy(float dy) {
mDrawerCallback.scrollBy(dy);
}
@Override
public boolean shouldLayoutHeaderBottom() {
return mDrawerCallback.shouldLayoutHeaderBottom();
}
@Override
public boolean canScroll(float dy) {
return mDrawerCallback.canScroll(dy);
}
@Override
public boolean isScrollContent(float x, float y) {
return mDrawerCallback.isScrollContent(x, y);
}
@Override
public void cancelTouch() {
mDrawerCallback.cancelTouch();
}
@Override
public void topChanged(int offset) {
mDrawerCallback.topChanged(offset);
}
private SimpleDrawerCallback mDrawerCallback;
private OnScrollListener mOnScrollListener = new OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
@ -49,10 +88,11 @@ public class UserMediaTimelineFragment extends BaseSupportFragment
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final View view = getView();
assert view != null;
if (view == null) throw new AssertionError();
final Context context = view.getContext();
mAdapter = new MediaTimelineAdapter(context);
final StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mDrawerCallback = new SimpleDrawerCallback(mRecyclerView);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setOnScrollListener(mOnScrollListener);
@ -62,7 +102,7 @@ public class UserMediaTimelineFragment extends BaseSupportFragment
public void setListShown(boolean shown) {
mRecyclerView.setVisibility(shown ? View.VISIBLE : View.GONE);
mProgress.setVisibility(shown ? View.GONE : View.VISIBLE);
mProgressContainer.setVisibility(shown ? View.GONE : View.VISIBLE);
}
public int getStatuses(final long maxId, final long sinceId) {
@ -76,8 +116,8 @@ public class UserMediaTimelineFragment extends BaseSupportFragment
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mProgressContainer = view.findViewById(R.id.progress_container);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
mProgress = (ProgressBar) view.findViewById(R.id.progress);
}
@Override

View File

@ -1,123 +1,42 @@
/*
* 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.graphics.Rect;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager;
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.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.OnScrollListener;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.ParcelableStatusesAdapter;
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration;
import org.mariotaku.twidere.loader.support.UserTimelineLoader;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback;
import java.util.List;
/**
* Created by mariotaku on 14/11/5.
* Created by mariotaku on 14/12/2.
*/
public class UserTimelineFragment extends BaseSupportFragment
implements LoaderCallbacks<List<ParcelableStatus>>, OnRefreshListener, DrawerCallback {
private SwipeRefreshLayout mSwipeRefreshLayout;
private RecyclerView mRecyclerView;
private ProgressBar mProgressBar;
private ParcelableStatusesAdapter mAdapter;
private OnScrollListener mOnScrollListener = new OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
final LoaderManager lm = getLoaderManager();
if (lm.hasRunningLoaders()) return;
if (layoutManager.findLastVisibleItemPosition() == mAdapter.getItemCount() - 1) {
getStatuses(mAdapter.getStatus(mAdapter.getStatusCount() - 1).id, 0);
}
}
};
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final View view = getView();
assert view != null;
final Context context = view.getContext();
final boolean compact = Utils.isCompactCards(context);
mSwipeRefreshLayout.setOnRefreshListener(this);
mSwipeRefreshLayout.setColorSchemeColors(ThemeUtils.getUserAccentColor(context));
mAdapter = new ParcelableStatusesAdapter(context, compact);
final LinearLayoutManager layoutManager = new LinearLayoutManager(context);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
if (compact) {
mRecyclerView.addItemDecoration(new DividerItemDecoration(context, layoutManager.getOrientation()));
}
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setOnScrollListener(mOnScrollListener);
getLoaderManager().initLoader(0, getArguments(), this);
setListShown(false);
}
private void setListShown(boolean shown) {
mProgressBar.setVisibility(shown ? View.GONE : View.VISIBLE);
mSwipeRefreshLayout.setVisibility(shown ? View.VISIBLE : View.GONE);
}
public int getStatuses(final long maxId, final long sinceId) {
final Bundle args = new Bundle(getArguments());
args.putLong(EXTRA_MAX_ID, maxId);
args.putLong(EXTRA_SINCE_ID, sinceId);
getLoaderManager().restartLoader(0, args, this);
return -1;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_layout);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
mProgressBar = (ProgressBar) view.findViewById(R.id.progress);
}
@Override
protected void fitSystemWindows(Rect insets) {
super.fitSystemWindows(insets);
// mRecyclerView.setClipToPadding(false);
// mRecyclerView.setPadding(insets.left, insets.top, insets.right, insets.bottom);
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_recycler_view, container, false);
}
public class UserTimelineFragment extends ParcelableStatusesFragment {
@Override
public Loader<List<ParcelableStatus>> onCreateLoader(int id, Bundle args) {
// mSwipeRefreshLayout.setRefreshing(true);
final List<ParcelableStatus> data = mAdapter.getData();
setRefreshing(true);
final List<ParcelableStatus> data = getAdapterData();
final Context context = getActivity();
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
final long maxId = args.getLong(EXTRA_MAX_ID, -1);
@ -129,57 +48,4 @@ public class UserTimelineFragment extends BaseSupportFragment
null, tabPosition);
}
@Override
public void onLoadFinished(Loader<List<ParcelableStatus>> loader, List<ParcelableStatus> data) {
mSwipeRefreshLayout.setRefreshing(false);
mAdapter.setData(data);
setListShown(true);
}
@Override
public void onLoaderReset(Loader<List<ParcelableStatus>> loader) {
}
@Override
public void onRefresh() {
if (mAdapter.getStatusCount() > 0) {
getStatuses(0, mAdapter.getStatus(0).id);
} else {
getStatuses(0, 0);
}
}
@Override
public void fling(float velocity) {
mRecyclerView.fling(0, (int) velocity);
}
@Override
public void scrollBy(float dy) {
mRecyclerView.scrollBy(0, (int) dy);
}
@Override
public boolean canScroll(float dy) {
return mRecyclerView.canScrollVertically((int) dy);
}
@Override
public boolean isScrollContent(float x, float y) {
final int[] location = new int[2];
mRecyclerView.getLocationOnScreen(location);
return x >= location[0] && x <= location[0] && y >= location[1] && y <= location[1];
}
@Override
public void cancelTouch() {
mRecyclerView.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_CANCEL, 0, 0, 0));
}
@Override
public void topChanged(int offset) {
}
}

View File

@ -7,24 +7,65 @@ import android.graphics.drawable.Drawable;
public class EmptyDrawable extends Drawable {
@Override
public void draw(final Canvas canvas) {
private final int mIntrinsicWidth, mIntrinsicHeight, mMinimumWidth, mMinimumHeight;
}
@Override
public int getMinimumHeight() {
return mMinimumHeight;
}
@Override
public int getOpacity() {
return PixelFormat.TRANSPARENT;
}
@Override
public int getMinimumWidth() {
return mMinimumWidth;
}
@Override
public void setAlpha(final int alpha) {
@Override
public int getIntrinsicHeight() {
return mIntrinsicHeight;
}
}
@Override
public int getIntrinsicWidth() {
return mIntrinsicWidth;
}
@Override
public void setColorFilter(final ColorFilter cf) {
}
public EmptyDrawable() {
this(0, 0, -1, -1);
}
public EmptyDrawable(int minimumWidth, int minimumHeight, int intrinsicWidth, int intrinsicHeight) {
mMinimumWidth = minimumWidth;
mMinimumHeight = minimumHeight;
mIntrinsicWidth = intrinsicWidth;
mIntrinsicHeight = intrinsicHeight;
}
public EmptyDrawable(Drawable drawableToCopySize) {
mMinimumWidth = drawableToCopySize.getMinimumWidth();
mMinimumHeight = drawableToCopySize.getMinimumHeight();
mIntrinsicWidth = drawableToCopySize.getIntrinsicWidth();
mIntrinsicHeight = drawableToCopySize.getIntrinsicHeight();
}
@Override
public void draw(final Canvas canvas) {
}
@Override
public int getOpacity() {
return PixelFormat.TRANSPARENT;
}
@Override
public void setAlpha(final int alpha) {
}
@Override
public void setColorFilter(final ColorFilter cf) {
}
}

View File

@ -27,149 +27,150 @@ import org.mariotaku.twidere.fragment.support.ActivitiesAboutMeFragment;
import org.mariotaku.twidere.fragment.support.ActivitiesByFriendsFragment;
import org.mariotaku.twidere.fragment.support.DirectMessagesFragment;
import org.mariotaku.twidere.fragment.support.HomeTimelineFragment;
import org.mariotaku.twidere.fragment.support.HomeTimelineListFragment;
import org.mariotaku.twidere.fragment.support.MentionsTimelineFragment;
import org.mariotaku.twidere.fragment.support.SearchStatusesFragment;
import org.mariotaku.twidere.fragment.support.TrendsSuggectionsFragment;
import org.mariotaku.twidere.fragment.support.UserFavoritesFragment;
import org.mariotaku.twidere.fragment.support.UserListTimelineFragment;
import org.mariotaku.twidere.fragment.support.UserTimelineFragmentOld;
import org.mariotaku.twidere.fragment.support.UserTimelineFragment;
import java.util.Comparator;
import java.util.Map.Entry;
public enum CustomTabConfiguration2 implements Constants {
HOME_TIMELINE(HomeTimelineFragment.class, R.string.home, R.drawable.ic_action_home,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 0, false),
HOME_TIMELINE(HomeTimelineFragment.class, R.string.home, R.drawable.ic_action_home,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 0, false),
MENTIONS_TIMELINE(MentionsTimelineFragment.class, R.string.mentions, R.drawable.ic_action_at,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 1, false),
MENTIONS_TIMELINE(MentionsTimelineFragment.class, R.string.mentions, R.drawable.ic_action_at,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 1, false),
DIRECT_MESSAGES(DirectMessagesFragment.class, R.string.direct_messages, R.drawable.ic_action_message,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 2, false),
DIRECT_MESSAGES(DirectMessagesFragment.class, R.string.direct_messages, R.drawable.ic_action_message,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 2, false),
TRENDS_SUGGESTIONS(TrendsSuggectionsFragment.class, R.string.trends, R.drawable.ic_action_hashtag,
CustomTabConfiguration.ACCOUNT_NONE, CustomTabConfiguration.FIELD_TYPE_NONE, 3, true),
TRENDS_SUGGESTIONS(TrendsSuggectionsFragment.class, R.string.trends, R.drawable.ic_action_hashtag,
CustomTabConfiguration.ACCOUNT_NONE, CustomTabConfiguration.FIELD_TYPE_NONE, 3, true),
FAVORITES(UserFavoritesFragment.class, R.string.favorites, R.drawable.ic_action_star,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_USER, 4),
FAVORITES(UserFavoritesFragment.class, R.string.favorites, R.drawable.ic_action_star,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_USER, 4),
USER_TIMELINE(UserTimelineFragmentOld.class, R.string.users_statuses, R.drawable.ic_action_quote,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_USER, 5),
USER_TIMELINE(UserTimelineFragment.class, R.string.users_statuses, R.drawable.ic_action_quote,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_USER, 5),
SEARCH_STATUSES(SearchStatusesFragment.class, R.string.search_statuses, R.drawable.ic_action_search,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_TEXT, R.string.query,
EXTRA_QUERY, 6),
SEARCH_STATUSES(SearchStatusesFragment.class, R.string.search_statuses, R.drawable.ic_action_search,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_TEXT, R.string.query,
EXTRA_QUERY, 6),
LIST_TIMELINE(UserListTimelineFragment.class, R.string.list_timeline, R.drawable.ic_action_list,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_USER_LIST, 7),
LIST_TIMELINE(UserListTimelineFragment.class, R.string.list_timeline, R.drawable.ic_action_list,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_USER_LIST, 7),
ACTIVITIES_ABOUT_ME(ActivitiesAboutMeFragment.class, R.string.activities_about_me,
R.drawable.ic_action_user, CustomTabConfiguration.ACCOUNT_OPTIONAL,
CustomTabConfiguration.FIELD_TYPE_NONE, 8),
ACTIVITIES_ABOUT_ME(ActivitiesAboutMeFragment.class, R.string.activities_about_me,
R.drawable.ic_action_user, CustomTabConfiguration.ACCOUNT_OPTIONAL,
CustomTabConfiguration.FIELD_TYPE_NONE, 8),
ACTIVITIES_BY_FRIENDS(ActivitiesByFriendsFragment.class, R.string.activities_by_friends,
R.drawable.ic_action_accounts, CustomTabConfiguration.ACCOUNT_REQUIRED,
CustomTabConfiguration.FIELD_TYPE_NONE, 9);
ACTIVITIES_BY_FRIENDS(ActivitiesByFriendsFragment.class, R.string.activities_by_friends,
R.drawable.ic_action_accounts, CustomTabConfiguration.ACCOUNT_REQUIRED,
CustomTabConfiguration.FIELD_TYPE_NONE, 9);
public static final int FIELD_TYPE_NONE = 0;
public static final int FIELD_TYPE_USER = 1;
public static final int FIELD_TYPE_USER_LIST = 2;
public static final int FIELD_TYPE_TEXT = 3;
public static final int FIELD_TYPE_NONE = 0;
public static final int FIELD_TYPE_USER = 1;
public static final int FIELD_TYPE_USER_LIST = 2;
public static final int FIELD_TYPE_TEXT = 3;
public static final int ACCOUNT_NONE = 0;
public static final int ACCOUNT_REQUIRED = 1;
public static final int ACCOUNT_OPTIONAL = 2;
public static final int ACCOUNT_NONE = 0;
public static final int ACCOUNT_REQUIRED = 1;
public static final int ACCOUNT_OPTIONAL = 2;
private final int title, icon, secondaryFieldType, secondaryFieldTitle, sortPosition, accountRequirement;
private final Class<? extends Fragment> cls;
private final String secondaryFieldTextKey;
private final boolean singleTab;
private final int title, icon, secondaryFieldType, secondaryFieldTitle, sortPosition, accountRequirement;
private final Class<? extends Fragment> cls;
private final String secondaryFieldTextKey;
private final boolean singleTab;
CustomTabConfiguration2(final Class<? extends Fragment> cls, final int title, final int icon,
final int accountRequirement, final int secondaryFieldType, final int sortPosition) {
this(cls, title, icon, accountRequirement, secondaryFieldType, 0, EXTRA_TEXT, sortPosition, false);
}
CustomTabConfiguration2(final Class<? extends Fragment> cls, final int title, final int icon,
final int accountRequirement, final int secondaryFieldType, final int sortPosition) {
this(cls, title, icon, accountRequirement, secondaryFieldType, 0, EXTRA_TEXT, sortPosition, false);
}
CustomTabConfiguration2(final Class<? extends Fragment> cls, final int title, final int icon,
final int accountRequirement, final int secondaryFieldType, final int sortPosition, final boolean singleTab) {
this(cls, title, icon, accountRequirement, secondaryFieldType, 0, EXTRA_TEXT, sortPosition, singleTab);
}
CustomTabConfiguration2(final Class<? extends Fragment> cls, final int title, final int icon,
final int accountRequirement, final int secondaryFieldType, final int sortPosition, final boolean singleTab) {
this(cls, title, icon, accountRequirement, secondaryFieldType, 0, EXTRA_TEXT, sortPosition, singleTab);
}
CustomTabConfiguration2(final Class<? extends Fragment> cls, final int title, final int icon,
final int accountRequirement, final int secondaryFieldType, final int secondaryFieldTitle,
final String secondaryFieldTextKey, final int sortPosition) {
this(cls, title, icon, accountRequirement, secondaryFieldType, 0, secondaryFieldTextKey, sortPosition, false);
}
CustomTabConfiguration2(final Class<? extends Fragment> cls, final int title, final int icon,
final int accountRequirement, final int secondaryFieldType, final int secondaryFieldTitle,
final String secondaryFieldTextKey, final int sortPosition) {
this(cls, title, icon, accountRequirement, secondaryFieldType, 0, secondaryFieldTextKey, sortPosition, false);
}
CustomTabConfiguration2(final Class<? extends Fragment> cls, final int title, final int icon,
final int accountRequirement, final int secondaryFieldType, final int secondaryFieldTitle,
final String secondaryFieldTextKey, final int sortPosition, final boolean singleTab) {
this.cls = cls;
this.title = title;
this.icon = icon;
this.sortPosition = sortPosition;
this.accountRequirement = accountRequirement;
this.secondaryFieldType = secondaryFieldType;
this.secondaryFieldTitle = secondaryFieldTitle;
this.secondaryFieldTextKey = secondaryFieldTextKey;
this.singleTab = singleTab;
}
CustomTabConfiguration2(final Class<? extends Fragment> cls, final int title, final int icon,
final int accountRequirement, final int secondaryFieldType, final int secondaryFieldTitle,
final String secondaryFieldTextKey, final int sortPosition, final boolean singleTab) {
this.cls = cls;
this.title = title;
this.icon = icon;
this.sortPosition = sortPosition;
this.accountRequirement = accountRequirement;
this.secondaryFieldType = secondaryFieldType;
this.secondaryFieldTitle = secondaryFieldTitle;
this.secondaryFieldTextKey = secondaryFieldTextKey;
this.singleTab = singleTab;
}
public int getAccountRequirement() {
return accountRequirement;
}
public int getAccountRequirement() {
return accountRequirement;
}
public int getDefaultIcon() {
return icon;
}
public int getDefaultIcon() {
return icon;
}
public int getDefaultTitle() {
return title;
}
public int getDefaultTitle() {
return title;
}
public Class<? extends Fragment> getFragmentClass() {
return cls;
}
public Class<? extends Fragment> getFragmentClass() {
return cls;
}
public String getSecondaryFieldTextKey() {
return secondaryFieldTextKey;
}
public String getSecondaryFieldTextKey() {
return secondaryFieldTextKey;
}
public int getSecondaryFieldTitle() {
return secondaryFieldTitle;
}
public int getSecondaryFieldTitle() {
return secondaryFieldTitle;
}
public int getSecondaryFieldType() {
return secondaryFieldType;
}
public int getSecondaryFieldType() {
return secondaryFieldType;
}
public int getSortPosition() {
return sortPosition;
}
public int getSortPosition() {
return sortPosition;
}
public boolean isSingleTab() {
return singleTab;
}
public boolean isSingleTab() {
return singleTab;
}
@Override
public String toString() {
return "CustomTabConfiguration{title=" + title + ", icon=" + icon + ", secondaryFieldType="
+ secondaryFieldType + ", secondaryFieldTitle=" + secondaryFieldTitle + ", sortPosition="
+ sortPosition + ", accountRequirement=" + accountRequirement + ", cls=" + cls
+ ", secondaryFieldTextKey=" + secondaryFieldTextKey + ", singleTab=" + singleTab + "}";
}
@Override
public String toString() {
return "CustomTabConfiguration{title=" + title + ", icon=" + icon + ", secondaryFieldType="
+ secondaryFieldType + ", secondaryFieldTitle=" + secondaryFieldTitle + ", sortPosition="
+ sortPosition + ", accountRequirement=" + accountRequirement + ", cls=" + cls
+ ", secondaryFieldTextKey=" + secondaryFieldTextKey + ", singleTab=" + singleTab + "}";
}
public static class CustomTabConfigurationComparator implements Comparator<Entry<String, CustomTabConfiguration2>> {
public static class CustomTabConfigurationComparator implements Comparator<Entry<String, CustomTabConfiguration2>> {
public static final CustomTabConfigurationComparator SINGLETON = new CustomTabConfigurationComparator();
public static final CustomTabConfigurationComparator SINGLETON = new CustomTabConfigurationComparator();
@Override
public int compare(final Entry<String, CustomTabConfiguration2> lhs,
final Entry<String, CustomTabConfiguration2> rhs) {
return lhs.getValue().getSortPosition() - rhs.getValue().getSortPosition();
}
@Override
public int compare(final Entry<String, CustomTabConfiguration2> lhs,
final Entry<String, CustomTabConfiguration2> rhs) {
return lhs.getValue().getSortPosition() - rhs.getValue().getSortPosition();
}
}
}
}

View File

@ -30,8 +30,6 @@ import org.mariotaku.twidere.provider.TweetStore.CachedUsers;
import org.mariotaku.twidere.provider.TweetStore.DirectMessages.ConversationEntries;
import org.mariotaku.twidere.util.ParseUtils;
import java.util.Date;
import twitter4j.URLEntity;
import twitter4j.User;
@ -74,6 +72,8 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
public final int followers_count, friends_count, statuses_count, favorites_count, listed_count;
public final int background_color, link_color, text_color;
public final boolean is_cache;
public ParcelableUser(final long account_id, final long id, final String name,
@ -102,6 +102,9 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
statuses_count = 0;
favorites_count = 0;
listed_count = 0;
background_color = 0;
link_color = 0;
text_color = 0;
is_cache = true;
}
@ -140,6 +143,9 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
is_cache = true;
description_unescaped = toPlainText(description_html);
is_following = cursor.getInt(cursor.getColumnIndex(CachedUsers.IS_FOLLOWING)) == 1;
background_color = cursor.getInt(cursor.getColumnIndex(CachedUsers.BACKGROUND_COLOR));
link_color = cursor.getInt(cursor.getColumnIndex(CachedUsers.LINK_COLOR));
text_color = cursor.getInt(cursor.getColumnIndex(CachedUsers.TEXT_COLOR));
}
public ParcelableUser(final JSONParcel in) {
@ -152,6 +158,9 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
name = in.readString("name");
screen_name = in.readString("screen_name");
description_plain = in.readString("description_plain");
description_html = in.readString("description_html");
description_expanded = in.readString("description_expanded");
description_unescaped = in.readString("description_unescaped");
location = in.readString("location");
profile_image_url = in.readString("profile_image_url");
profile_banner_url = in.readString("profile_banner_url");
@ -163,11 +172,11 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
favorites_count = in.readInt("favorites_count");
listed_count = in.readInt("listed_count");
is_cache = in.readBoolean("is_cache");
description_html = in.readString("description_html");
description_expanded = in.readString("description_expanded");
url_expanded = in.readString("url_expanded");
is_following = in.readBoolean("is_following");
description_unescaped = in.readString("description_unescaped");
background_color = in.readInt("background_color");
link_color = in.readInt("link_color");
text_color = in.readInt("text_color");
}
public ParcelableUser(final Parcel in) {
@ -180,6 +189,9 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
name = in.readString();
screen_name = in.readString();
description_plain = in.readString();
description_html = in.readString();
description_expanded = in.readString();
description_unescaped = in.readString();
location = in.readString();
profile_image_url = in.readString();
profile_banner_url = in.readString();
@ -191,11 +203,11 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
favorites_count = in.readInt();
listed_count = in.readInt();
is_cache = in.readInt() == 1;
description_html = in.readString();
description_expanded = in.readString();
url_expanded = in.readString();
is_following = in.readInt() == 1;
description_unescaped = in.readString();
background_color = in.readInt();
link_color = in.readInt();
text_color = in.readInt();
}
public ParcelableUser(final User user, final long account_id) {
@ -207,7 +219,7 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
this.account_id = account_id;
final URLEntity[] urls_url_entities = user.getURLEntities();
id = user.getId();
created_at = getTime(user.getCreatedAt());
created_at = user.getCreatedAt().getTime();
is_protected = user.isProtected();
is_verified = user.isVerified();
name = user.getName();
@ -215,6 +227,7 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
description_plain = user.getDescription();
description_html = formatUserDescription(user);
description_expanded = formatExpandedUserDescription(user);
description_unescaped = toPlainText(description_html);
location = user.getLocation();
profile_image_url = ParseUtils.parseString(user.getProfileImageUrlHttps());
profile_banner_url = user.getProfileBannerImageUrl();
@ -229,7 +242,9 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
listed_count = user.getListedCount();
is_cache = false;
is_following = user.isFollowing();
description_unescaped = toPlainText(description_html);
background_color = ParseUtils.parseColor(user.getProfileBackgroundColor(), 0);
link_color = ParseUtils.parseColor(user.getProfileLinkColor(), 0);
text_color = ParseUtils.parseColor(user.getProfileTextColor(), 0);
}
@Override
@ -290,6 +305,9 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
out.writeString("name", name);
out.writeString("screen_name", screen_name);
out.writeString("description_plain", description_plain);
out.writeString("description_html", description_html);
out.writeString("description_expanded", description_expanded);
out.writeString("description_unescaped", description_unescaped);
out.writeString("location", location);
out.writeString("profile_image_url", profile_image_url);
out.writeString("profile_banner_url", profile_banner_url);
@ -301,11 +319,11 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
out.writeInt("favorites_count", favorites_count);
out.writeInt("listed_count", listed_count);
out.writeBoolean("is_cache", is_cache);
out.writeString("description_html", description_html);
out.writeString("description_expanded", description_expanded);
out.writeString("url_expanded", url_expanded);
out.writeBoolean("is_following", is_following);
out.writeString("description_unescaped", description_unescaped);
out.writeInt("background_color", background_color);
out.writeInt("link_color", link_color);
out.writeInt("text_color", text_color);
}
@Override
@ -319,6 +337,9 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
out.writeString(name);
out.writeString(screen_name);
out.writeString(description_plain);
out.writeString(description_html);
out.writeString(description_expanded);
out.writeString(description_unescaped);
out.writeString(location);
out.writeString(profile_image_url);
out.writeString(profile_banner_url);
@ -330,11 +351,11 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
out.writeInt(favorites_count);
out.writeInt(listed_count);
out.writeInt(is_cache ? 1 : 0);
out.writeString(description_html);
out.writeString(description_expanded);
out.writeString(url_expanded);
out.writeInt(is_following ? 1 : 0);
out.writeString(description_unescaped);
out.writeInt(background_color);
out.writeInt(link_color);
out.writeInt(text_color);
}
public static ContentValues makeCachedUserContentValues(final ParcelableUser user) {
@ -360,10 +381,10 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
values.put(CachedUsers.URL_EXPANDED, user.url_expanded);
values.put(CachedUsers.PROFILE_BANNER_URL, user.profile_banner_url);
values.put(CachedUsers.IS_FOLLOWING, user.is_following);
values.put(CachedUsers.BACKGROUND_COLOR, user.background_color);
values.put(CachedUsers.LINK_COLOR, user.link_color);
values.put(CachedUsers.TEXT_COLOR, user.text_color);
return values;
}
private static long getTime(final Date date) {
return date != null ? date.getTime() : 0;
}
}

View File

@ -241,6 +241,12 @@ public interface TweetStore {
public static final String LISTED_COUNT = "listed_count";
public static final String BACKGROUND_COLOR = "background_color";
public static final String LINK_COLOR = "link_color";
public static final String TEXT_COLOR = "text_color";
/**
* User's screen name of the status.<br>
* Type: TEXT
@ -254,13 +260,15 @@ public interface TweetStore {
public static final String PROFILE_IMAGE_URL = "profile_image_url";
public static final String[] COLUMNS = new String[]{_ID, USER_ID, CREATED_AT, NAME, SCREEN_NAME,
DESCRIPTION_PLAIN, LOCATION, URL, PROFILE_IMAGE_URL, PROFILE_BANNER_URL, IS_PROTECTED, IS_VERIFIED,
IS_FOLLOWING, FOLLOWERS_COUNT, FRIENDS_COUNT, STATUSES_COUNT, FAVORITES_COUNT, LISTED_COUNT, DESCRIPTION_HTML,
DESCRIPTION_EXPANDED, URL_EXPANDED};
DESCRIPTION_PLAIN, LOCATION, URL, PROFILE_IMAGE_URL, PROFILE_BANNER_URL, IS_PROTECTED,
IS_VERIFIED, IS_FOLLOWING, FOLLOWERS_COUNT, FRIENDS_COUNT, STATUSES_COUNT, FAVORITES_COUNT,
LISTED_COUNT, DESCRIPTION_HTML, DESCRIPTION_EXPANDED, URL_EXPANDED, BACKGROUND_COLOR,
LINK_COLOR, TEXT_COLOR};
public static final String[] TYPES = new String[]{TYPE_PRIMARY_KEY, TYPE_INT_UNIQUE, TYPE_INT, TYPE_TEXT,
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_BOOLEAN, TYPE_BOOLEAN,
TYPE_BOOLEAN, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT};
public static final String[] TYPES = new String[]{TYPE_PRIMARY_KEY, TYPE_INT_UNIQUE, TYPE_INT,
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_BOOLEAN,
TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_TEXT,
TYPE_TEXT, TYPE_TEXT, TYPE_INT, TYPE_INT, TYPE_INT};
}

View File

@ -131,6 +131,7 @@ public final class ContentValuesCreator implements TwidereConstants {
values.put(CachedUsers.NAME, user.getName());
values.put(CachedUsers.SCREEN_NAME, user.getScreenName());
values.put(CachedUsers.PROFILE_IMAGE_URL, profile_image_url);
values.put(CachedUsers.PROFILE_BANNER_URL, user.getProfileBannerImageUrl());
values.put(CachedUsers.CREATED_AT, user.getCreatedAt().getTime());
values.put(CachedUsers.IS_PROTECTED, user.isProtected());
values.put(CachedUsers.IS_VERIFIED, user.isVerified());
@ -145,10 +146,12 @@ public final class ContentValuesCreator implements TwidereConstants {
values.put(CachedUsers.DESCRIPTION_HTML, Utils.formatUserDescription(user));
values.put(CachedUsers.DESCRIPTION_EXPANDED, Utils.formatExpandedUserDescription(user));
values.put(CachedUsers.URL, url);
values.put(CachedUsers.URL_EXPANDED,
url != null && urls != null && urls.length > 0 ? ParseUtils.parseString(urls[0].getExpandedURL())
: null);
values.put(CachedUsers.PROFILE_BANNER_URL, user.getProfileBannerImageUrl());
if (url != null && urls != null && urls.length > 0) {
values.put(CachedUsers.URL_EXPANDED, ParseUtils.parseString(urls[0].getExpandedURL()));
}
values.put(CachedUsers.BACKGROUND_COLOR, ParseUtils.parseColor(user.getProfileBackgroundColor(), 0));
values.put(CachedUsers.LINK_COLOR, ParseUtils.parseColor(user.getProfileLinkColor(), 0));
values.put(CachedUsers.TEXT_COLOR, ParseUtils.parseColor(user.getProfileTextColor(), 0));
return values;
}

View File

@ -19,8 +19,6 @@
package org.mariotaku.twidere.util;
import static org.mariotaku.twidere.util.CompareUtils.classEquals;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
@ -38,6 +36,7 @@ import org.mariotaku.twidere.fragment.support.ActivitiesAboutMeFragment;
import org.mariotaku.twidere.fragment.support.ActivitiesByFriendsFragment;
import org.mariotaku.twidere.fragment.support.DirectMessagesFragment;
import org.mariotaku.twidere.fragment.support.HomeTimelineFragment;
import org.mariotaku.twidere.fragment.support.HomeTimelineListFragment;
import org.mariotaku.twidere.fragment.support.InvalidTabFragment;
import org.mariotaku.twidere.fragment.support.MentionsTimelineFragment;
import org.mariotaku.twidere.fragment.support.RetweetsOfMeFragment;
@ -46,7 +45,7 @@ import org.mariotaku.twidere.fragment.support.StaggeredHomeTimelineFragment;
import org.mariotaku.twidere.fragment.support.TrendsSuggectionsFragment;
import org.mariotaku.twidere.fragment.support.UserFavoritesFragment;
import org.mariotaku.twidere.fragment.support.UserListTimelineFragment;
import org.mariotaku.twidere.fragment.support.UserTimelineFragmentOld;
import org.mariotaku.twidere.fragment.support.UserTimelineFragment;
import org.mariotaku.twidere.model.CustomTabConfiguration;
import org.mariotaku.twidere.model.CustomTabConfiguration.ExtraConfiguration;
import org.mariotaku.twidere.model.SupportTabSpec;
@ -59,280 +58,282 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import static org.mariotaku.twidere.util.CompareUtils.classEquals;
public class CustomTabUtils implements Constants {
private static final HashMap<String, CustomTabConfiguration> CUSTOM_TABS_CONFIGURATION_MAP = new HashMap<String, CustomTabConfiguration>();
private static final HashMap<String, Integer> CUSTOM_TABS_ICON_NAME_MAP = new HashMap<String, Integer>();
private static final HashMap<String, CustomTabConfiguration> CUSTOM_TABS_CONFIGURATION_MAP = new HashMap<String, CustomTabConfiguration>();
private static final HashMap<String, Integer> CUSTOM_TABS_ICON_NAME_MAP = new HashMap<String, Integer>();
static {
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_HOME_TIMELINE, new CustomTabConfiguration(
HomeTimelineFragment.class, R.string.home, R.drawable.ic_action_home,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 0, false));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_MENTIONS_TIMELINE, new CustomTabConfiguration(
MentionsTimelineFragment.class, R.string.mentions, R.drawable.ic_action_at,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 1, false,
ExtraConfiguration.newBoolean(EXTRA_MY_FOLLOWING_ONLY, R.string.following_only, false)));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_DIRECT_MESSAGES, new CustomTabConfiguration(
DirectMessagesFragment.class, R.string.direct_messages, R.drawable.ic_action_message,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 2, false));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_TRENDS_SUGGESTIONS, new CustomTabConfiguration(
TrendsSuggectionsFragment.class, R.string.trends, R.drawable.ic_action_hashtag,
CustomTabConfiguration.ACCOUNT_NONE, CustomTabConfiguration.FIELD_TYPE_NONE, 3, true));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_FAVORITES, new CustomTabConfiguration(UserFavoritesFragment.class,
R.string.favorites, R.drawable.ic_action_star, CustomTabConfiguration.ACCOUNT_REQUIRED,
CustomTabConfiguration.FIELD_TYPE_USER, 4));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_USER_TIMELINE, new CustomTabConfiguration(
UserTimelineFragmentOld.class, R.string.users_statuses, R.drawable.ic_action_quote,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_USER, 5));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_SEARCH_STATUSES, new CustomTabConfiguration(
SearchStatusesFragment.class, R.string.search_statuses, R.drawable.ic_action_search,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_TEXT, R.string.query,
EXTRA_QUERY, 6));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_LIST_TIMELINE, new CustomTabConfiguration(
UserListTimelineFragment.class, R.string.list_timeline, R.drawable.ic_action_list,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_USER_LIST, 7));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_ACTIVITIES_ABOUT_ME, new CustomTabConfiguration(
ActivitiesAboutMeFragment.class, R.string.activities_about_me, R.drawable.ic_action_user,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 8));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_ACTIVITIES_BY_FRIENDS, new CustomTabConfiguration(
ActivitiesByFriendsFragment.class, R.string.activities_by_friends,
R.drawable.ic_action_accounts, CustomTabConfiguration.ACCOUNT_REQUIRED,
CustomTabConfiguration.FIELD_TYPE_NONE, 9));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_RETWEETS_OF_ME, new CustomTabConfiguration(
RetweetsOfMeFragment.class, R.string.retweets_of_me, R.drawable.ic_action_retweet,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_NONE, 10));
if (Utils.hasStaggeredTimeline()) {
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_STAGGERED_HOME_TIMELINE, new CustomTabConfiguration(
StaggeredHomeTimelineFragment.class, R.string.staggered_home_timeline,
R.drawable.ic_action_view_quilt, CustomTabConfiguration.ACCOUNT_OPTIONAL,
CustomTabConfiguration.FIELD_TYPE_NONE, 11, false));
}
static {
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_HOME_TIMELINE, new CustomTabConfiguration(
HomeTimelineFragment.class, R.string.home, R.drawable.ic_action_home,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 0, false));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_MENTIONS_TIMELINE, new CustomTabConfiguration(
MentionsTimelineFragment.class, R.string.mentions, R.drawable.ic_action_at,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 1, false,
ExtraConfiguration.newBoolean(EXTRA_MY_FOLLOWING_ONLY, R.string.following_only, false)));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_DIRECT_MESSAGES, new CustomTabConfiguration(
DirectMessagesFragment.class, R.string.direct_messages, R.drawable.ic_action_message,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 2, false));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_TRENDS_SUGGESTIONS, new CustomTabConfiguration(
TrendsSuggectionsFragment.class, R.string.trends, R.drawable.ic_action_hashtag,
CustomTabConfiguration.ACCOUNT_NONE, CustomTabConfiguration.FIELD_TYPE_NONE, 3, true));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_FAVORITES, new CustomTabConfiguration(UserFavoritesFragment.class,
R.string.favorites, R.drawable.ic_action_star, CustomTabConfiguration.ACCOUNT_REQUIRED,
CustomTabConfiguration.FIELD_TYPE_USER, 4));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_USER_TIMELINE, new CustomTabConfiguration(
UserTimelineFragment.class, R.string.users_statuses, R.drawable.ic_action_quote,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_USER, 5));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_SEARCH_STATUSES, new CustomTabConfiguration(
SearchStatusesFragment.class, R.string.search_statuses, R.drawable.ic_action_search,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_TEXT, R.string.query,
EXTRA_QUERY, 6));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_LIST_TIMELINE, new CustomTabConfiguration(
UserListTimelineFragment.class, R.string.list_timeline, R.drawable.ic_action_list,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_USER_LIST, 7));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_ACTIVITIES_ABOUT_ME, new CustomTabConfiguration(
ActivitiesAboutMeFragment.class, R.string.activities_about_me, R.drawable.ic_action_user,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 8));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_ACTIVITIES_BY_FRIENDS, new CustomTabConfiguration(
ActivitiesByFriendsFragment.class, R.string.activities_by_friends,
R.drawable.ic_action_accounts, CustomTabConfiguration.ACCOUNT_REQUIRED,
CustomTabConfiguration.FIELD_TYPE_NONE, 9));
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_RETWEETS_OF_ME, new CustomTabConfiguration(
RetweetsOfMeFragment.class, R.string.retweets_of_me, R.drawable.ic_action_retweet,
CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_NONE, 10));
if (Utils.hasStaggeredTimeline()) {
CUSTOM_TABS_CONFIGURATION_MAP.put(TAB_TYPE_STAGGERED_HOME_TIMELINE, new CustomTabConfiguration(
StaggeredHomeTimelineFragment.class, R.string.staggered_home_timeline,
R.drawable.ic_action_view_quilt, CustomTabConfiguration.ACCOUNT_OPTIONAL,
CustomTabConfiguration.FIELD_TYPE_NONE, 11, false));
}
CUSTOM_TABS_ICON_NAME_MAP.put("accounts", R.drawable.ic_action_accounts);
CUSTOM_TABS_ICON_NAME_MAP.put("hashtag", R.drawable.ic_action_hashtag);
CUSTOM_TABS_ICON_NAME_MAP.put("heart", R.drawable.ic_action_heart);
CUSTOM_TABS_ICON_NAME_MAP.put("home", R.drawable.ic_action_home);
CUSTOM_TABS_ICON_NAME_MAP.put("list", R.drawable.ic_action_list);
CUSTOM_TABS_ICON_NAME_MAP.put("mention", R.drawable.ic_action_at);
CUSTOM_TABS_ICON_NAME_MAP.put("message", R.drawable.ic_action_message);
CUSTOM_TABS_ICON_NAME_MAP.put("quote", R.drawable.ic_action_quote);
CUSTOM_TABS_ICON_NAME_MAP.put("search", R.drawable.ic_action_search);
CUSTOM_TABS_ICON_NAME_MAP.put("staggered", R.drawable.ic_action_view_quilt);
CUSTOM_TABS_ICON_NAME_MAP.put("star", R.drawable.ic_action_star);
CUSTOM_TABS_ICON_NAME_MAP.put("trends", R.drawable.ic_action_trends);
CUSTOM_TABS_ICON_NAME_MAP.put("twidere", R.drawable.ic_action_twidere);
CUSTOM_TABS_ICON_NAME_MAP.put("twitter", R.drawable.ic_action_twitter);
CUSTOM_TABS_ICON_NAME_MAP.put("user", R.drawable.ic_action_user);
}
CUSTOM_TABS_ICON_NAME_MAP.put("accounts", R.drawable.ic_action_accounts);
CUSTOM_TABS_ICON_NAME_MAP.put("hashtag", R.drawable.ic_action_hashtag);
CUSTOM_TABS_ICON_NAME_MAP.put("heart", R.drawable.ic_action_heart);
CUSTOM_TABS_ICON_NAME_MAP.put("home", R.drawable.ic_action_home);
CUSTOM_TABS_ICON_NAME_MAP.put("list", R.drawable.ic_action_list);
CUSTOM_TABS_ICON_NAME_MAP.put("mention", R.drawable.ic_action_at);
CUSTOM_TABS_ICON_NAME_MAP.put("message", R.drawable.ic_action_message);
CUSTOM_TABS_ICON_NAME_MAP.put("quote", R.drawable.ic_action_quote);
CUSTOM_TABS_ICON_NAME_MAP.put("search", R.drawable.ic_action_search);
CUSTOM_TABS_ICON_NAME_MAP.put("staggered", R.drawable.ic_action_view_quilt);
CUSTOM_TABS_ICON_NAME_MAP.put("star", R.drawable.ic_action_star);
CUSTOM_TABS_ICON_NAME_MAP.put("trends", R.drawable.ic_action_trends);
CUSTOM_TABS_ICON_NAME_MAP.put("twidere", R.drawable.ic_action_twidere);
CUSTOM_TABS_ICON_NAME_MAP.put("twitter", R.drawable.ic_action_twitter);
CUSTOM_TABS_ICON_NAME_MAP.put("user", R.drawable.ic_action_user);
}
public static String findTabIconKey(final int iconRes) {
for (final Entry<String, Integer> entry : getIconMap().entrySet()) {
if (entry.getValue() == iconRes) return entry.getKey();
}
return null;
}
public static String findTabIconKey(final int iconRes) {
for (final Entry<String, Integer> entry : getIconMap().entrySet()) {
if (entry.getValue() == iconRes) return entry.getKey();
}
return null;
}
public static String findTabType(final Class<? extends Fragment> cls) {
for (final Entry<String, CustomTabConfiguration> entry : getConfiguraionMap().entrySet()) {
if (classEquals(cls, entry.getValue().getFragmentClass())) return entry.getKey();
}
return null;
}
public static String findTabType(final Class<? extends Fragment> cls) {
for (final Entry<String, CustomTabConfiguration> entry : getConfiguraionMap().entrySet()) {
if (classEquals(cls, entry.getValue().getFragmentClass())) return entry.getKey();
}
return null;
}
public static SupportTabSpec getAddedTabAt(final Context context, final int position) {
if (context == null || position < 0) return null;
final ContentResolver resolver = context.getContentResolver();
final Cursor cur = resolver.query(Tabs.CONTENT_URI, Tabs.COLUMNS, Tabs.POSITION + " = " + position, null,
Tabs.DEFAULT_SORT_ORDER);
final int idxName = cur.getColumnIndex(Tabs.NAME), idxIcon = cur.getColumnIndex(Tabs.ICON), idxType = cur
.getColumnIndex(Tabs.TYPE), idxArguments = cur.getColumnIndex(Tabs.ARGUMENTS), idxExtras = cur
.getColumnIndex(Tabs.EXTRAS);
try {
if (cur.getCount() == 0) return null;
cur.moveToFirst();
final String type = cur.getString(idxType);
final CustomTabConfiguration conf = getTabConfiguration(type);
if (conf == null) return null;
final String icon_type = cur.getString(idxIcon);
final String name = cur.getString(idxName);
final Bundle args = ParseUtils.jsonToBundle(cur.getString(idxArguments));
args.putInt(EXTRA_TAB_POSITION, position);
args.putBundle(EXTRA_EXTRAS, ParseUtils.jsonToBundle(cur.getString(idxExtras)));
final Class<? extends Fragment> fragment = conf.getFragmentClass();
return new SupportTabSpec(name != null ? name : getTabTypeName(context, type), getTabIconObject(icon_type),
type, fragment, args, position);
} finally {
cur.close();
}
}
public static SupportTabSpec getAddedTabAt(final Context context, final int position) {
if (context == null || position < 0) return null;
final ContentResolver resolver = context.getContentResolver();
final Cursor cur = resolver.query(Tabs.CONTENT_URI, Tabs.COLUMNS, Tabs.POSITION + " = " + position, null,
Tabs.DEFAULT_SORT_ORDER);
final int idxName = cur.getColumnIndex(Tabs.NAME), idxIcon = cur.getColumnIndex(Tabs.ICON), idxType = cur
.getColumnIndex(Tabs.TYPE), idxArguments = cur.getColumnIndex(Tabs.ARGUMENTS), idxExtras = cur
.getColumnIndex(Tabs.EXTRAS);
try {
if (cur.getCount() == 0) return null;
cur.moveToFirst();
final String type = cur.getString(idxType);
final CustomTabConfiguration conf = getTabConfiguration(type);
if (conf == null) return null;
final String icon_type = cur.getString(idxIcon);
final String name = cur.getString(idxName);
final Bundle args = ParseUtils.jsonToBundle(cur.getString(idxArguments));
args.putInt(EXTRA_TAB_POSITION, position);
args.putBundle(EXTRA_EXTRAS, ParseUtils.jsonToBundle(cur.getString(idxExtras)));
final Class<? extends Fragment> fragment = conf.getFragmentClass();
return new SupportTabSpec(name != null ? name : getTabTypeName(context, type), getTabIconObject(icon_type),
type, fragment, args, position);
} finally {
cur.close();
}
}
public static CustomTabConfiguration getAddedTabConfigurationAt(final Context context, final int position) {
if (context == null || position < 0) return null;
final ContentResolver resolver = context.getContentResolver();
final Cursor cur = resolver.query(Tabs.CONTENT_URI, Tabs.COLUMNS, Tabs.POSITION + " = " + position, null,
Tabs.DEFAULT_SORT_ORDER);
final int idxType = cur.getColumnIndex(Tabs.TYPE);
try {
if (cur.getCount() == 0) return null;
cur.moveToFirst();
final String type = cur.getString(idxType);
return getTabConfiguration(type);
} finally {
cur.close();
}
}
public static CustomTabConfiguration getAddedTabConfigurationAt(final Context context, final int position) {
if (context == null || position < 0) return null;
final ContentResolver resolver = context.getContentResolver();
final Cursor cur = resolver.query(Tabs.CONTENT_URI, Tabs.COLUMNS, Tabs.POSITION + " = " + position, null,
Tabs.DEFAULT_SORT_ORDER);
final int idxType = cur.getColumnIndex(Tabs.TYPE);
try {
if (cur.getCount() == 0) return null;
cur.moveToFirst();
final String type = cur.getString(idxType);
return getTabConfiguration(type);
} finally {
cur.close();
}
}
public static int getAddedTabPosition(final Context context, final String type) {
if (context == null || type == null) return -1;
final ContentResolver resolver = context.getContentResolver();
final String where = Tabs.TYPE + " = ?";
final Cursor cur = resolver.query(Tabs.CONTENT_URI, new String[] { Tabs.POSITION }, where,
new String[] { type }, Tabs.DEFAULT_SORT_ORDER);
if (cur == null) return -1;
final int position;
if (cur.getCount() > 0) {
cur.moveToFirst();
position = cur.getInt(cur.getColumnIndex(Tabs.POSITION));
} else {
position = -1;
}
cur.close();
return position;
}
public static int getAddedTabPosition(final Context context, final String type) {
if (context == null || type == null) return -1;
final ContentResolver resolver = context.getContentResolver();
final String where = Tabs.TYPE + " = ?";
final Cursor cur = resolver.query(Tabs.CONTENT_URI, new String[]{Tabs.POSITION}, where,
new String[]{type}, Tabs.DEFAULT_SORT_ORDER);
if (cur == null) return -1;
final int position;
if (cur.getCount() > 0) {
cur.moveToFirst();
position = cur.getInt(cur.getColumnIndex(Tabs.POSITION));
} else {
position = -1;
}
cur.close();
return position;
}
public static String getAddedTabTypeAt(final Context context, final int position) {
if (context == null || position < 0) return null;
final ContentResolver resolver = context.getContentResolver();
final Cursor cur = resolver.query(Tabs.CONTENT_URI, Tabs.COLUMNS, Tabs.POSITION + " = " + position, null,
Tabs.DEFAULT_SORT_ORDER);
final int idx_type = cur.getColumnIndex(Tabs.TYPE);
try {
if (cur.getCount() == 0) return null;
cur.moveToFirst();
return cur.getString(idx_type);
} finally {
cur.close();
}
}
public static String getAddedTabTypeAt(final Context context, final int position) {
if (context == null || position < 0) return null;
final ContentResolver resolver = context.getContentResolver();
final Cursor cur = resolver.query(Tabs.CONTENT_URI, Tabs.COLUMNS, Tabs.POSITION + " = " + position, null,
Tabs.DEFAULT_SORT_ORDER);
final int idx_type = cur.getColumnIndex(Tabs.TYPE);
try {
if (cur.getCount() == 0) return null;
cur.moveToFirst();
return cur.getString(idx_type);
} finally {
cur.close();
}
}
public static HashMap<String, CustomTabConfiguration> getConfiguraionMap() {
return new HashMap<String, CustomTabConfiguration>(CUSTOM_TABS_CONFIGURATION_MAP);
}
public static HashMap<String, CustomTabConfiguration> getConfiguraionMap() {
return new HashMap<String, CustomTabConfiguration>(CUSTOM_TABS_CONFIGURATION_MAP);
}
public static List<SupportTabSpec> getHomeTabs(final Context context) {
if (context == null) return Collections.emptyList();
final ContentResolver resolver = context.getContentResolver();
final Cursor cur = resolver.query(Tabs.CONTENT_URI, Tabs.COLUMNS, null, null, Tabs.DEFAULT_SORT_ORDER);
if (cur == null) return Collections.emptyList();
final ArrayList<SupportTabSpec> tabs = new ArrayList<SupportTabSpec>();
cur.moveToFirst();
final int idxName = cur.getColumnIndex(Tabs.NAME), idxIcon = cur.getColumnIndex(Tabs.ICON), idxType = cur
.getColumnIndex(Tabs.TYPE), idxArguments = cur.getColumnIndex(Tabs.ARGUMENTS), idxExtras = cur
.getColumnIndex(Tabs.EXTRAS), idxPosition = cur.getColumnIndex(Tabs.POSITION);
while (!cur.isAfterLast()) {
final String type = cur.getString(idxType);
final int position = cur.getInt(idxPosition);
final String iconType = cur.getString(idxIcon);
final String name = cur.getString(idxName);
final Bundle args = ParseUtils.jsonToBundle(cur.getString(idxArguments));
args.putInt(EXTRA_TAB_POSITION, position);
args.putBundle(EXTRA_EXTRAS, ParseUtils.jsonToBundle(cur.getString(idxExtras)));
final CustomTabConfiguration conf = getTabConfiguration(type);
final Class<? extends Fragment> cls = conf != null ? conf.getFragmentClass() : InvalidTabFragment.class;
tabs.add(new SupportTabSpec(name != null ? name : getTabTypeName(context, type),
getTabIconObject(iconType), type, cls, args, position));
cur.moveToNext();
}
cur.close();
Collections.sort(tabs);
return tabs;
}
public static List<SupportTabSpec> getHomeTabs(final Context context) {
if (context == null) return Collections.emptyList();
final ContentResolver resolver = context.getContentResolver();
final Cursor cur = resolver.query(Tabs.CONTENT_URI, Tabs.COLUMNS, null, null, Tabs.DEFAULT_SORT_ORDER);
if (cur == null) return Collections.emptyList();
final ArrayList<SupportTabSpec> tabs = new ArrayList<SupportTabSpec>();
cur.moveToFirst();
final int idxName = cur.getColumnIndex(Tabs.NAME), idxIcon = cur.getColumnIndex(Tabs.ICON), idxType = cur
.getColumnIndex(Tabs.TYPE), idxArguments = cur.getColumnIndex(Tabs.ARGUMENTS), idxExtras = cur
.getColumnIndex(Tabs.EXTRAS), idxPosition = cur.getColumnIndex(Tabs.POSITION);
while (!cur.isAfterLast()) {
final String type = cur.getString(idxType);
final int position = cur.getInt(idxPosition);
final String iconType = cur.getString(idxIcon);
final String name = cur.getString(idxName);
final Bundle args = ParseUtils.jsonToBundle(cur.getString(idxArguments));
args.putInt(EXTRA_TAB_POSITION, position);
args.putBundle(EXTRA_EXTRAS, ParseUtils.jsonToBundle(cur.getString(idxExtras)));
final CustomTabConfiguration conf = getTabConfiguration(type);
final Class<? extends Fragment> cls = conf != null ? conf.getFragmentClass() : InvalidTabFragment.class;
tabs.add(new SupportTabSpec(name != null ? name : getTabTypeName(context, type),
getTabIconObject(iconType), type, cls, args, position));
cur.moveToNext();
}
cur.close();
Collections.sort(tabs);
return tabs;
}
public static HashMap<String, Integer> getIconMap() {
return new HashMap<String, Integer>(CUSTOM_TABS_ICON_NAME_MAP);
}
public static HashMap<String, Integer> getIconMap() {
return new HashMap<String, Integer>(CUSTOM_TABS_ICON_NAME_MAP);
}
public static CustomTabConfiguration getTabConfiguration(final String key) {
if (key == null) return null;
return CUSTOM_TABS_CONFIGURATION_MAP.get(key);
}
public static CustomTabConfiguration getTabConfiguration(final String key) {
if (key == null) return null;
return CUSTOM_TABS_CONFIGURATION_MAP.get(key);
}
public static Drawable getTabIconDrawable(final Context context, final Object iconObj) {
return getTabIconDrawable(context.getResources(), iconObj);
}
public static Drawable getTabIconDrawable(final Context context, final Object iconObj) {
return getTabIconDrawable(context.getResources(), iconObj);
}
public static Drawable getTabIconDrawable(final Resources res, final Object iconObj) {
if (res == null) return null;
if (iconObj instanceof Integer) {
try {
return res.getDrawable((Integer) iconObj);
} catch (final Resources.NotFoundException e) {
// Ignore.
}
} else if (iconObj instanceof Bitmap)
return new BitmapDrawable(res, (Bitmap) iconObj);
else if (iconObj instanceof Drawable)
return (Drawable) iconObj;
else if (iconObj instanceof File) {
final Bitmap b = getTabIconFromFile((File) iconObj, res);
if (b != null) return new BitmapDrawable(res, b);
}
return res.getDrawable(R.drawable.ic_action_list);
}
public static Drawable getTabIconDrawable(final Resources res, final Object iconObj) {
if (res == null) return null;
if (iconObj instanceof Integer) {
try {
return res.getDrawable((Integer) iconObj);
} catch (final Resources.NotFoundException e) {
// Ignore.
}
} else if (iconObj instanceof Bitmap)
return new BitmapDrawable(res, (Bitmap) iconObj);
else if (iconObj instanceof Drawable)
return (Drawable) iconObj;
else if (iconObj instanceof File) {
final Bitmap b = getTabIconFromFile((File) iconObj, res);
if (b != null) return new BitmapDrawable(res, b);
}
return res.getDrawable(R.drawable.ic_action_list);
}
public static Bitmap getTabIconFromFile(final File file, final Resources res) {
if (file == null || !file.exists()) return null;
final String path = file.getPath();
final BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, o);
if (o.outHeight <= 0 || o.outWidth <= 0) return null;
o.inSampleSize = (int) (Math.max(o.outWidth, o.outHeight) / (48 * res.getDisplayMetrics().density));
o.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, o);
}
public static Bitmap getTabIconFromFile(final File file, final Resources res) {
if (file == null || !file.exists()) return null;
final String path = file.getPath();
final BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, o);
if (o.outHeight <= 0 || o.outWidth <= 0) return null;
o.inSampleSize = (int) (Math.max(o.outWidth, o.outHeight) / (48 * res.getDisplayMetrics().density));
o.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, o);
}
public static Object getTabIconObject(final String type) {
if (type == null) return R.drawable.ic_action_list;
final Integer value = CUSTOM_TABS_ICON_NAME_MAP.get(type);
if (value != null)
return value;
else if (type.contains("/")) {
try {
final File file = new File(type);
if (file.exists()) return file;
} catch (final Exception e) {
return R.drawable.ic_action_list;
}
}
return R.drawable.ic_action_list;
}
public static Object getTabIconObject(final String type) {
if (type == null) return R.drawable.ic_action_list;
final Integer value = CUSTOM_TABS_ICON_NAME_MAP.get(type);
if (value != null)
return value;
else if (type.contains("/")) {
try {
final File file = new File(type);
if (file.exists()) return file;
} catch (final Exception e) {
return R.drawable.ic_action_list;
}
}
return R.drawable.ic_action_list;
}
public static String getTabTypeName(final Context context, final String type) {
if (context == null) return null;
final CustomTabConfiguration conf = getTabConfiguration(type);
final Integer res_id = conf != null ? conf.getDefaultTitle() : null;
return res_id != null ? context.getString(res_id) : null;
}
public static String getTabTypeName(final Context context, final String type) {
if (context == null) return null;
final CustomTabConfiguration conf = getTabConfiguration(type);
final Integer res_id = conf != null ? conf.getDefaultTitle() : null;
return res_id != null ? context.getString(res_id) : null;
}
public static boolean isSingleTab(final String type) {
if (type == null) return false;
final CustomTabConfiguration conf = getTabConfiguration(type);
return conf != null && conf.isSingleTab();
}
public static boolean isSingleTab(final String type) {
if (type == null) return false;
final CustomTabConfiguration conf = getTabConfiguration(type);
return conf != null && conf.isSingleTab();
}
public static boolean isTabAdded(final Context context, final String type) {
if (context == null || type == null) return false;
final ContentResolver resolver = context.getContentResolver();
final String where = Tabs.TYPE + " = ?";
final Cursor cur = resolver.query(Tabs.CONTENT_URI, new String[0], where, new String[] { type },
Tabs.DEFAULT_SORT_ORDER);
if (cur == null) return false;
final boolean added = cur.getCount() > 0;
cur.close();
return added;
}
public static boolean isTabAdded(final Context context, final String type) {
if (context == null || type == null) return false;
final ContentResolver resolver = context.getContentResolver();
final String where = Tabs.TYPE + " = ?";
final Cursor cur = resolver.query(Tabs.CONTENT_URI, new String[0], where, new String[]{type},
Tabs.DEFAULT_SORT_ORDER);
if (cur == null) return false;
final boolean added = cur.getCount() > 0;
cur.close();
return added;
}
public static boolean isTabTypeValid(final String type) {
return type != null && CUSTOM_TABS_CONFIGURATION_MAP.containsKey(type);
}
public static boolean isTabTypeValid(final String type) {
return type != null && CUSTOM_TABS_CONFIGURATION_MAP.containsKey(type);
}
}

View File

@ -0,0 +1,78 @@
/*
* 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.util;
import android.os.SystemClock;
import android.support.v7.widget.RecyclerView;
import android.view.MotionEvent;
import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback;
/**
* Created by mariotaku on 14/12/2.
*/
public class SimpleDrawerCallback implements DrawerCallback {
private final RecyclerView mRecyclerView;
public SimpleDrawerCallback(RecyclerView recyclerView) {
mRecyclerView = recyclerView;
}
@Override
public void fling(float velocity) {
mRecyclerView.fling(0, (int) velocity);
}
@Override
public void scrollBy(float dy) {
mRecyclerView.scrollBy(0, (int) dy);
}
@Override
public boolean canScroll(float dy) {
return mRecyclerView.canScrollVertically((int) dy);
}
@Override
public boolean isScrollContent(float x, float y) {
final int[] location = new int[2];
mRecyclerView.getLocationOnScreen(location);
return x >= location[0] && x <= location[0] && y >= location[1] && y <= location[1];
}
@Override
public void cancelTouch() {
mRecyclerView.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_CANCEL, 0, 0, 0));
}
@Override
public boolean shouldLayoutHeaderBottom() {
return true;
}
@Override
public void topChanged(int offset) {
}
}

View File

@ -2784,8 +2784,11 @@ public final class Utils implements Constants, TwitterConstants {
}
public static boolean isMyRetweet(final ParcelableStatus status) {
if (status == null) return false;
return status.retweeted_by_id == status.account_id || status.my_retweet_id > 0;
return status != null && isMyRetweet(status.account_id, status.retweeted_by_id, status.my_retweet_id);
}
public static boolean isMyRetweet(final long account_id, final long retweeted_by_id, final long my_retweet_id) {
return retweeted_by_id == account_id || my_retweet_id > 0;
}
public static boolean isMyUserName(final Context context, final String screen_name) {
@ -2852,11 +2855,6 @@ public final class Utils implements Constants, TwitterConstants {
&& networkInfo.isConnected();
}
public static boolean isPlainListStyle(final Context context) {
final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
return prefs != null && prefs.getBoolean(KEY_PLAIN_LIST_STYLE, false);
}
public static boolean isRedirected(final int code) {
return code == 301 || code == 302 || code == 307;
}
@ -3027,7 +3025,7 @@ public final class Utils implements Constants, TwitterConstants {
activity.startActivity(intent);
}
public static void openStatus(final Context context, final ParcelableStatus status) {
public static void openStatus(final Context context, final ParcelableStatus status, Bundle activityOptions) {
if (context == null || status == null) return;
final long account_id = status.account_id, status_id = status.id;
final Bundle extras = new Bundle();
@ -3040,7 +3038,11 @@ public final class Utils implements Constants, TwitterConstants {
final Intent intent = new Intent(Intent.ACTION_VIEW, builder.build());
intent.setExtrasClassLoader(context.getClassLoader());
intent.putExtras(extras);
context.startActivity(intent);
if (context instanceof Activity) {
ActivityCompat.startActivity((Activity) context, intent, activityOptions);
} else {
context.startActivity(intent);
}
}
public static void openStatuses(final Activity activity, final List<ParcelableStatus> statuses) {
@ -3999,7 +4001,7 @@ public final class Utils implements Constants, TwitterConstants {
@SafeVarargs
public static Bundle makeSceneTransitionOption(final Activity activity,
final Pair<View, String>... sharedElements) {
final Pair<View, String>... sharedElements) {
if (ThemeUtils.isTransparentBackground(activity)) return null;
return ActivityOptionsCompat.makeSceneTransitionAnimation(activity, sharedElements).toBundle();
}

View File

@ -80,79 +80,6 @@ public class HeaderDrawerLayout extends ViewGroup {
this(context, null);
}
private static int makeChildMeasureSpec(int spec, int padding) {
final int size = MeasureSpec.getSize(spec), mode = MeasureSpec.getMode(spec);
return MeasureSpec.makeMeasureSpec(size - padding, mode);
}
private boolean isUsingDragHelper() {
return mUsingDragHelper;
}
private void setScrollingHeaderByGesture(boolean scrolling) {
mScrollingHeaderByGesture = scrolling;
}
public void flingHeader(float velocity) {
if (mTouchDown) {
mScroller.abortAnimation();
return;
}
mScroller.fling(0, getHeaderTop(), 0, (int) velocity, 0, 0,
mContainer.getHeaderTopMinimum(), mContainer.getHeaderTopMaximum());
ViewCompat.postInvalidateOnAnimation(this);
}
private void flingCallback(float velocity) {
mDrawerCallback.fling(velocity);
}
@Override
public void computeScroll() {
boolean invalidate = mDragHelper.continueSettling(true);
if (!mTouchDown && mScroller.computeScrollOffset()) {
if (!invalidate) {
offsetHeaderBy(mScroller.getCurrY() - getHeaderTop());
}
invalidate = true;
}
updateViewOffset();
if (invalidate) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
private void scrollByCallback(float dy) {
setScrollingContentCallback(true);
mDrawerCallback.scrollBy(dy);
}
private boolean isScrollContentCallback(float x, float y) {
return mDrawerCallback.isScrollContent(x, y);
}
private void cancelTouchCallback() {
mDrawerCallback.cancelTouch();
}
@Override
protected void onFinishInflate() {
if (getChildCount() != 1) {
throw new IllegalArgumentException("Add subview by XML is not allowed.");
}
}
private boolean canScrollCallback(float dy) {
return mDrawerCallback.canScroll(dy);
}
public void setDrawerCallback(DrawerCallback callback) {
mDrawerCallback = callback;
}
private void updateViewOffset() {
}
@Override
public boolean dispatchTouchEvent(@NonNull MotionEvent ev) {
switch (ev.getAction()) {
@ -188,41 +115,60 @@ public class HeaderDrawerLayout extends ViewGroup {
for (int i = 0, j = getChildCount(); i < j; i++) {
final View child = getChildAt(i);
final int left = getPaddingLeft(), right = left + child.getMeasuredWidth();
final int top = i == 0 ? mHeaderOffset + getPaddingTop() : getChildAt(i - 1).getBottom();
final int top;
if (i == 0) {
if (shouldLayoutHeaderBottomCallback() && child.getHeight() != 0) {
final int heightDelta = child.getMeasuredHeight() - child.getHeight();
top = mHeaderOffset + getPaddingTop() - heightDelta;
} else {
top = mHeaderOffset + getPaddingTop();
}
} else {
top = getChildAt(i - 1).getBottom();
}
final int bottom = top + child.getMeasuredHeight();
child.layout(left, top, right, bottom);
notifyOffsetChanged();
}
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
mDragHelper.processTouchEvent(event);
return true;
}
public View getHeader() {
return mContainer.getHeader();
public void flingHeader(float velocity) {
if (mTouchDown) {
mScroller.abortAnimation();
return;
}
mScroller.fling(0, getHeaderTop(), 0, (int) velocity, 0, 0,
mContainer.getHeaderTopMinimum(), mContainer.getHeaderTopMaximum());
ViewCompat.postInvalidateOnAnimation(this);
}
public View getContent() {
return mContainer.getContent();
}
private int getScrollRange() {
return mContainer.getScrollRange();
public View getHeader() {
return mContainer.getHeader();
}
@Override
public void computeScroll() {
boolean invalidate = mDragHelper.continueSettling(true);
if (!mTouchDown && mScroller.computeScrollOffset()) {
if (!invalidate) {
offsetHeaderBy(mScroller.getCurrY() - getHeaderTop());
}
invalidate = true;
}
updateViewOffset();
if (invalidate) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
public int getHeaderTop() {
return mContainer.getTop();
}
private void offsetHeaderBy(int dy) {
final int prevTop = mContainer.getTop();
final int clampedDy = MathUtils.clamp(prevTop + dy, getHeaderTopMinimum(), getHeaderTopMaximum()) - prevTop;
mContainer.offsetTopAndBottom(clampedDy);
}
public int getHeaderTopMaximum() {
return mContainer.getHeaderTopMaximum();
}
@ -231,6 +177,82 @@ public class HeaderDrawerLayout extends ViewGroup {
return mContainer.getHeaderTopMinimum();
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
mDragHelper.processTouchEvent(event);
return true;
}
@Override
protected void onFinishInflate() {
if (getChildCount() != 1) {
throw new IllegalArgumentException("Add subview by XML is not allowed.");
}
}
public void setDrawerCallback(DrawerCallback callback) {
mDrawerCallback = callback;
}
private boolean canScrollCallback(float dy) {
return mDrawerCallback.canScroll(dy);
}
private void cancelTouchCallback() {
mDrawerCallback.cancelTouch();
}
private void flingCallback(float velocity) {
mDrawerCallback.fling(velocity);
}
private float getDragTouchSlop() {
return mDragHelper.getTouchSlop();
}
private int getScrollRange() {
return mContainer.getScrollRange();
}
private boolean isScrollContentCallback(float x, float y) {
return mDrawerCallback.isScrollContent(x, y);
}
private boolean isScrollingContentCallback() {
return mScrollingContentCallback;
}
private void setScrollingContentCallback(boolean scrolling) {
mScrollingContentCallback = scrolling;
}
private boolean isScrollingHeaderByHelper() {
return mDragCallback.isScrollingHeaderByHelper();
}
private boolean isTouchingScrollableContent() {
return mTouchingScrollableContent;
}
private boolean isUsingDragHelper() {
return mUsingDragHelper;
}
private boolean isValidScroll(float direction, float other) {
return Math.abs(direction) > getDragTouchSlop() && Math.abs(direction) > Math.abs(other);
}
private static int makeChildMeasureSpec(int spec, int padding) {
final int size = MeasureSpec.getSize(spec), mode = MeasureSpec.getMode(spec);
return MeasureSpec.makeMeasureSpec(size - padding, mode);
}
private void notifyOffsetChanged() {
final int top = getHeaderTop();
mHeaderOffset = top - getPaddingTop();
mDrawerCallback.topChanged(top);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final View child = getChildAt(0);
@ -242,47 +264,41 @@ public class HeaderDrawerLayout extends ViewGroup {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private boolean isTouchingScrollableContent() {
return mTouchingScrollableContent;
private void offsetHeaderBy(int dy) {
final int prevTop = mContainer.getTop();
final int clampedDy = MathUtils.clamp(prevTop + dy, getHeaderTopMinimum(), getHeaderTopMaximum()) - prevTop;
mContainer.offsetTopAndBottom(clampedDy);
}
private void notifyOffsetChanged() {
final int top = getHeaderTop();
mHeaderOffset = top - getPaddingTop();
mDrawerCallback.topChanged(top);
private void scrollByCallback(float dy) {
setScrollingContentCallback(true);
mDrawerCallback.scrollBy(dy);
}
private float getDragTouchSlop() {
return mDragHelper.getTouchSlop();
private void setScrollingHeaderByGesture(boolean scrolling) {
mScrollingHeaderByGesture = scrolling;
}
private boolean isValidScroll(float direction, float other) {
return Math.abs(direction) > getDragTouchSlop() && Math.abs(direction) > Math.abs(other);
private boolean shouldLayoutHeaderBottomCallback() {
return mDrawerCallback.shouldLayoutHeaderBottom();
}
private boolean isScrollingHeaderByHelper() {
return mDragCallback.isScrollingHeaderByHelper();
}
private boolean isScrollingContentCallback() {
return mScrollingContentCallback;
}
private void setScrollingContentCallback(boolean scrolling) {
mScrollingContentCallback = scrolling;
private void updateViewOffset() {
}
public static interface DrawerCallback {
void fling(float velocity);
void scrollBy(float dy);
boolean canScroll(float dy);
void cancelTouch();
void fling(float velocity);
boolean isScrollContent(float x, float y);
void cancelTouch();
void scrollBy(float dy);
boolean shouldLayoutHeaderBottom();
void topChanged(int offset);
}
@ -369,12 +385,12 @@ public class HeaderDrawerLayout extends ViewGroup {
mScrollingHeaderByHelper = false;
return current;
}
if (dy > 0 && mDrawer.canScrollCallback(-dy)) {
if (dy > 0 && mDrawer.canScrollCallback(-dy) && mDrawer.isTouchingScrollableContent()) {
if (!mDrawer.isUsingDragHelper()) {
// Scrolling up while list still has space to scroll, so make header still
mScrollingHeaderByHelper = false;
return current;
} else if (mDrawer.isTouchingScrollableContent()) {
} else {
mDrawer.scrollByCallback(-dy);
mScrollingHeaderByHelper = false;
return current;
@ -428,16 +444,24 @@ public class HeaderDrawerLayout extends ViewGroup {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
final int top = mDrawer.getHeaderTop(), min = mDrawer.getHeaderTopMinimum();
if (velocityY > 0 && !mDrawer.canScrollCallback(-1)) {
// Fling down when list reached top, so we fling header down here
if (Math.abs(velocityY) > Math.abs(velocityX)) {
mDrawer.flingHeader(velocityY);
}
} else if (velocityY < 0 && top <= min && mDrawer.isScrollingContentCallback()) {
// Fling up when showing full content, so we fling list up here
if (Math.abs(velocityY) > Math.abs(velocityX)) {
mDrawer.flingCallback(-velocityY);
final boolean showingFullContent = top <= min, flingUp = velocityY < 0;
final boolean verticalFling = Math.abs(velocityY) > Math.abs(velocityX);
if (!verticalFling) return true;
if (showingFullContent) {
if (flingUp) {
// Fling list up when showing full content
if (mDrawer.isScrollingContentCallback()) {
mDrawer.flingCallback(-velocityY);
}
} else {
// Fling down when list reached top and not dragging user ViewDragHelper,
// so we fling header down here
if (!mDrawer.canScrollCallback(1) && !mDrawer.isUsingDragHelper()) {
mDrawer.flingHeader(velocityY);
}
}
} else {
// Header still visible
}
return true;
}
@ -464,22 +488,22 @@ public class HeaderDrawerLayout extends ViewGroup {
addView(mContentView = inflater.inflate(contentLayoutId, this, false));
}
public View getHeader() {
return mHeaderView;
}
public View getContent() {
return mContentView;
}
public int getHeaderTopMinimum() {
return mParent.getPaddingTop() - mHeaderView.getHeight();
public View getHeader() {
return mHeaderView;
}
public int getHeaderTopMaximum() {
return mParent.getPaddingTop();
}
public int getHeaderTopMinimum() {
return mParent.getPaddingTop() - mHeaderView.getHeight();
}
public int getScrollRange() {
return getHeaderTopMaximum() - getHeaderTopMinimum();
}

View File

@ -19,20 +19,10 @@
package org.mariotaku.twidere.view;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewOutlineProvider;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.view.iface.IExtendedView;
@ -42,9 +32,6 @@ public class ProfileBannerImageView extends ForegroundImageView implements IExte
private OnSizeChangedListener mOnSizeChangedListener;
private TouchInterceptor mTouchInterceptor;
private final Paint mClipPaint = new Paint();
private int mBottomClip;
public ProfileBannerImageView(final Context context) {
this(context, null);
}
@ -57,18 +44,6 @@ public class ProfileBannerImageView extends ForegroundImageView implements IExte
super(context, attrs, defStyle);
if (isInEditMode()) return;
setScaleType(ScaleType.CENTER_CROP);
mClipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
ViewCompat.setLayerType(this, ViewCompat.LAYER_TYPE_SOFTWARE, null);
} else {
setOutlineProvider(new CropOutlineProvider(this));
setClipToOutline(true);
}
}
@Override
public boolean hasOverlappingRendering() {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP;
}
@Override
@ -114,38 +89,4 @@ public class ProfileBannerImageView extends ForegroundImageView implements IExte
}
}
@Override
protected void dispatchDraw(final Canvas canvas) {
super.dispatchDraw(canvas);
if (mBottomClip != 0 && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
canvas.drawRect(getLeft(), getBottom() - mBottomClip - getTranslationY(), getRight(), getBottom(), mClipPaint);
}
}
public void setBottomClip(int bottom) {
mBottomClip = bottom;
invalidate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
invalidateOutline();
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static class CropOutlineProvider extends ViewOutlineProvider {
private final ProfileBannerImageView mImageView;
CropOutlineProvider(ProfileBannerImageView imageView) {
mImageView = imageView;
}
@Override
public void getOutline(View view, Outline outline) {
final int left = view.getLeft();
final int top = view.getTop();
final int right = view.getRight();
final int bottom = Math.round(view.getBottom() - mImageView.mBottomClip - view.getTranslationY());
outline.setRect(left, top, right, bottom);
}
}
}

View File

@ -85,7 +85,7 @@ public class TintedStatusFrameLayout extends FrameLayout {
if (context instanceof FitSystemWindowsCallback) {
((FitSystemWindowsCallback) context).fitSystemWindows(insets);
}
return false;
return super.fitSystemWindows(insets);
}
@Override
@ -99,7 +99,7 @@ public class TintedStatusFrameLayout extends FrameLayout {
canvas.drawRect(0, 0, canvas.getWidth(), mStatusBarHeight, mDrawColor ? mColorPaint : mBlackPaint);
}
protected void setStatusBarHeight(int height) {
public void setStatusBarHeight(int height) {
mStatusBarHeight = height;
invalidate();
}

View File

@ -0,0 +1,45 @@
/*
* 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.view.holder;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.View.OnClickListener;
import org.mariotaku.twidere.adapter.iface.IGapSupportedAdapter;
/**
* Created by mariotaku on 14/12/3.
*/
public class GapViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
private final IGapSupportedAdapter adapter;
public GapViewHolder(IGapSupportedAdapter adapter, View itemView) {
super(itemView);
this.adapter = adapter;
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
adapter.onGapClick(this, getPosition());
}
}

View File

@ -2,8 +2,8 @@ package org.mariotaku.twidere.view.holder;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.database.Cursor;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.View.OnClickListener;
@ -13,10 +13,11 @@ import android.widget.TextView;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.iface.IStatusesAdapter;
import org.mariotaku.twidere.constant.IntentConstants;
import org.mariotaku.twidere.fragment.support.StatusMenuDialogFragment;
import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatus.CursorIndices;
import org.mariotaku.twidere.util.ImageLoaderWrapper;
import org.mariotaku.twidere.util.UserColorNicknameUtils;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.view.CircularImageView;
import org.mariotaku.twidere.view.ShortTimeView;
@ -28,9 +29,9 @@ import static org.mariotaku.twidere.util.Utils.getUserTypeIconRes;
/**
* Created by mariotaku on 14/11/19.
*/
public class StatusViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
public class StatusViewHolder<Data> extends RecyclerView.ViewHolder implements OnClickListener {
private final IStatusesAdapter adapter;
private final IStatusesAdapter<Data> adapter;
private final ImageView retweetProfileImageView;
private final CircularImageView profileImageView;
@ -43,7 +44,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements OnClick
private final View mediaPreviewContainer;
private final TextView replyCountView, retweetCountView, favoriteCountView;
public StatusViewHolder(IStatusesAdapter adapter, View itemView) {
public StatusViewHolder(IStatusesAdapter<Data> adapter, View itemView) {
super(itemView);
this.adapter = adapter;
itemView.findViewById(R.id.item_content).setOnClickListener(this);
@ -63,8 +64,8 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements OnClick
replyCountView = (TextView) itemView.findViewById(R.id.reply_count);
retweetCountView = (TextView) itemView.findViewById(R.id.retweet_count);
favoriteCountView = (TextView) itemView.findViewById(R.id.favorite_count);
//TODO
// profileImageView.setSelectorColor(ThemeUtils.getUserHighlightColor(itemView.getContext()));
//TODO
// profileImageView.setSelectorColor(ThemeUtils.getUserHighlightColor(itemView.getContext()));
itemView.setOnClickListener(this);
profileImageView.setOnClickListener(this);
@ -90,12 +91,10 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements OnClick
replyRetweetView.setText(context.getString(R.string.name_retweeted, status.retweeted_by_name));
}
replyRetweetView.setVisibility(View.VISIBLE);
// replyRetweetView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_action_retweet, 0, 0, 0);
retweetProfileImageView.setVisibility(View.GONE);
} else if (status.in_reply_to_status_id > 0 && status.in_reply_to_user_id > 0) {
replyRetweetView.setText(context.getString(R.string.in_reply_to_name, status.in_reply_to_name));
replyRetweetView.setVisibility(View.VISIBLE);
// replyRetweetView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_action_reply, 0, 0, 0);
retweetProfileImageView.setVisibility(View.GONE);
} else {
replyRetweetView.setText(null);
@ -117,8 +116,8 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements OnClick
screenNameView.setText("@" + status.user_screen_name);
timeView.setTime(status.timestamp);
// final int userColor = UserColorNicknameUtils.getUserColor(context, status.user_id);
// profileImageView.setBorderColor(userColor);
final int userColor = UserColorNicknameUtils.getUserColor(context, status.user_id);
profileImageView.setBorderColor(userColor);
loader.displayProfileImage(profileImageView, status.user_profile_image_url);
@ -160,28 +159,141 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements OnClick
favoriteCountView.setActivated(status.is_favorite);
}
public void displayStatus(Cursor cursor, CursorIndices indices) {
final ImageLoaderWrapper loader = adapter.getImageLoader();
final Context context = adapter.getContext();
final int reply_count = cursor.getInt(indices.reply_count);
final int retweet_count = cursor.getInt(indices.retweet_count);
final int favorite_count = cursor.getInt(indices.favorite_count);
final long account_id = cursor.getLong(indices.account_id);
final long timestamp = cursor.getLong(indices.status_timestamp);
final long user_id = cursor.getLong(indices.user_id);
final long retweet_id = cursor.getLong(indices.retweet_id);
final long my_retweet_id = cursor.getLong(indices.my_retweet_id);
final long retweeted_by_id = cursor.getLong(indices.retweeted_by_user_id);
final long in_reply_to_status_id = cursor.getLong(indices.in_reply_to_status_id);
final long in_reply_to_user_id = cursor.getLong(indices.in_reply_to_user_id);
final boolean user_is_protected = cursor.getInt(indices.is_protected) == 1;
final String user_name = cursor.getString(indices.user_name);
final String user_screen_name = cursor.getString(indices.user_screen_name);
final String user_profile_image_url = cursor.getString(indices.user_profile_image_url);
final String retweeted_by_name = cursor.getString(indices.retweeted_by_user_name);
final String in_reply_to_name = cursor.getString(indices.in_reply_to_user_name);
final ParcelableMedia[] media = ParcelableMedia.fromJSONString(cursor.getString(indices.media));
if (retweet_id > 0) {
if (retweet_count == 2) {
replyRetweetView.setText(context.getString(R.string.name_and_another_retweeted,
retweeted_by_name));
} else if (retweet_count > 2) {
replyRetweetView.setText(context.getString(R.string.name_and_count_retweeted,
retweeted_by_name, retweet_count - 1));
} else {
replyRetweetView.setText(context.getString(R.string.name_retweeted, retweeted_by_name));
}
replyRetweetView.setVisibility(View.VISIBLE);
retweetProfileImageView.setVisibility(View.GONE);
} else if (in_reply_to_status_id > 0 && in_reply_to_user_id > 0) {
replyRetweetView.setText(context.getString(R.string.in_reply_to_name, in_reply_to_name));
replyRetweetView.setVisibility(View.VISIBLE);
retweetProfileImageView.setVisibility(View.GONE);
} else {
replyRetweetView.setText(null);
replyRetweetView.setVisibility(View.GONE);
replyRetweetView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
retweetProfileImageView.setVisibility(View.GONE);
}
final int typeIconRes = getUserTypeIconRes(cursor.getInt(indices.is_verified) == 1,
user_is_protected);
if (typeIconRes != 0) {
profileTypeView.setImageResource(typeIconRes);
profileTypeView.setVisibility(View.VISIBLE);
} else {
profileTypeView.setImageDrawable(null);
profileTypeView.setVisibility(View.GONE);
}
nameView.setText(user_name);
screenNameView.setText("@" + user_screen_name);
timeView.setTime(timestamp);
final int userColor = UserColorNicknameUtils.getUserColor(context, user_id);
profileImageView.setBorderColor(userColor);
loader.displayProfileImage(profileImageView, user_profile_image_url);
if (media != null && media.length > 0) {
final String text_plain = cursor.getString(indices.text_plain);
final String text_unescaped = cursor.getString(indices.text_unescaped);
final ParcelableMedia firstMedia = media[0];
if (text_plain.codePointCount(0, text_plain.length()) == firstMedia.end) {
textView.setText(text_unescaped.substring(0, firstMedia.start));
} else {
textView.setText(text_unescaped);
}
loader.displayPreviewImageWithCredentials(mediaPreviewView, firstMedia.media_url,
account_id, adapter.getImageLoadingHandler());
mediaPreviewContainer.setVisibility(View.VISIBLE);
} else {
final String text_unescaped = cursor.getString(indices.text_unescaped);
loader.cancelDisplayTask(mediaPreviewView);
textView.setText(text_unescaped);
mediaPreviewContainer.setVisibility(View.GONE);
}
if (reply_count > 0) {
replyCountView.setText(Utils.getLocalizedNumber(Locale.getDefault(), reply_count));
} else {
replyCountView.setText(null);
}
if (retweet_count > 0) {
retweetCountView.setText(Utils.getLocalizedNumber(Locale.getDefault(), retweet_count));
} else {
retweetCountView.setText(null);
}
if (favorite_count > 0) {
favoriteCountView.setText(Utils.getLocalizedNumber(Locale.getDefault(), favorite_count));
} else {
favoriteCountView.setText(null);
}
retweetCountView.setEnabled(!user_is_protected);
retweetCountView.setActivated(Utils.isMyRetweet(account_id, retweeted_by_id, my_retweet_id));
favoriteCountView.setActivated(cursor.getInt(indices.is_favorite) == 1);
}
public CardView getCardView() {
return (CardView) itemView.findViewById(R.id.card);
}
public CircularImageView getProfileImageView() {
return profileImageView;
}
@Override
public void onClick(View v) {
final Context context = itemView.getContext();
final ParcelableStatus status = adapter.getStatus(getPosition());
final int position = getPosition();
final ParcelableStatus status = adapter.getStatus(position);
switch (v.getId()) {
case R.id.item_content: {
Utils.openStatus(context, status);
adapter.onStatusClick(this, position);
break;
}
case R.id.menu: {
if (context instanceof FragmentActivity) {
final Bundle args = new Bundle();
args.putParcelable(IntentConstants.EXTRA_STATUS, status);
final StatusMenuDialogFragment f = new StatusMenuDialogFragment();
f.setArguments(args);
f.show(((FragmentActivity) context).getSupportFragmentManager(), "status_menu");
}
adapter.onItemMenuClick(this, position);
break;
}
case R.id.profile_image: {
Utils.openUserProfile(context, status.account_id, status.user_id,
status.user_screen_name, null);
adapter.onUserProfileClick(this, position);
break;
}
case R.id.reply_count: {

View File

@ -7,6 +7,7 @@
android:layout_margin="@dimen/element_spacing_small"
android:clickable="true"
android:foreground="?android:selectableItemBackground"
app:cardBackgroundColor="?cardItemBackgroundColor"
app:cardCornerRadius="2dp"
app:cardElevation="2dp">

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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/>.
-->
<TextView
android:id="@+id/gap_indicator"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/element_size_normal"
android:background="?android:selectableItemBackground"
android:gravity="center"
android:text="@string/load_more"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorPrimary"
android:textStyle="bold"/>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
android:id="@+id/card"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"

View File

@ -21,10 +21,5 @@
</android.support.v4.widget.SwipeRefreshLayout>
<ProgressBar
android:id="@+id/progress"
style="?android:progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
<include layout="@layout/layout_content_fragment_common"/>
</FrameLayout>

View File

@ -30,13 +30,18 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.mariotaku.twidere.view.ProfileBannerImageView
android:id="@+id/profile_banner"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
<FrameLayout
android:id="@+id/profile_banner_container"
android:layout_gravity="top"
android:scaleType="centerCrop"/>
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.mariotaku.twidere.view.ProfileBannerImageView
android:id="@+id/profile_banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"/>
</FrameLayout>
<org.mariotaku.twidere.view.HeaderDrawerLayout
android:id="@+id/user_profile_drawer"
@ -46,6 +51,4 @@
app:headerLayout="@layout/header_user"/>
</org.mariotaku.twidere.view.ExtendedFrameLayout>
<include layout="@layout/layout_content_fragment_common"/>
</FrameLayout>

View File

@ -5,7 +5,7 @@
android:layout_height="wrap_content">
<ImageView
android:id="@+id/profile_banner"
android:id="@+id/account_profile_banner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignBottom="@id/profile_container"
@ -35,7 +35,7 @@
android:layout_marginTop="@dimen/element_spacing_mlarge"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/account_selector"
android:id="@+id/other_accounts_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/profile_image"

View File

@ -6,6 +6,7 @@
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/element_spacing_normal"
@ -14,7 +15,6 @@
app:cardElevation="@dimen/elevation_card">
<LinearLayout
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
@ -48,8 +48,8 @@
android:layout_height="@dimen/element_size_mlarge"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:contentDescription="@string/profile_image"
android:layout_margin="@dimen/padding_profile_image_detail_page"
android:contentDescription="@string/profile_image"
android:scaleType="centerCrop"
app:border="true"
app:borderWidth="1dp"/>

View File

@ -43,7 +43,7 @@
android:layout_alignRight="@id/profile_image"
android:scaleType="fitCenter"/>
<org.mariotaku.twidere.view.ColorLabelLinearLayout
<org.mariotaku.twidere.view.ColorLabelRelativeLayout
android:id="@+id/profile_name_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -55,40 +55,37 @@
android:padding="@dimen/element_spacing_small"
app:ignorePadding="true">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/name"
android:layout_width="match_parent"
<Button
android:id="@+id/follow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/name"
android:textAppearance="?android:textAppearanceMedium"/>
android:layout_alignParentRight="true"
android:layout_centerInParent="true"
android:minWidth="48dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:layout_alignParentRight="true"
android:layout_toLeftOf="@id/follow"
android:orientation="vertical">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:textAppearanceMedium"/>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/screen_name"
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:text="@string/screen_name"
android:textAppearance="?android:textAppearanceSmall"/>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/following_you_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:singleLine="true"
android:text="@string/following_you"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorTertiary"
android:visibility="gone"/>
</LinearLayout>
</org.mariotaku.twidere.view.ColorLabelLinearLayout>
</org.mariotaku.twidere.view.ColorLabelRelativeLayout>
<android.support.v7.widget.CardView
android:id="@+id/card"
@ -101,6 +98,7 @@
app:cardElevation="@dimen/elevation_card">
<LinearLayout
android:id="@+id/card_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
@ -304,6 +302,9 @@
</LinearLayout>
</LinearLayout>
</LinearLayout>
<include layout="@layout/layout_content_fragment_common"/>
</android.support.v7.widget.CardView>
<org.mariotaku.twidere.view.AssetFontTextView

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<org.mariotaku.twidere.view.ProfileBannerImageView
android:id="@+id/profile_banner"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:scaleType="centerCrop"/>

View File

@ -23,7 +23,8 @@
<FrameLayout
android:id="@+id/progress_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:padding="@dimen/element_spacing_large">
<ProgressBar
style="?android:progressBarStyleLarge"
@ -38,7 +39,7 @@
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="16dp"
android:padding="@dimen/element_spacing_large"
android:visibility="gone">
<TextView

View File

@ -1,65 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2012 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Layout of a header item in PreferenceActivity. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/activatedBackgroundIndicator"
android:gravity="center_vertical"
android:minHeight="48dp"
android:paddingEnd="?android:attr/scrollbarSize">
<ImageView
android:id="@android:id/icon"
android:layout_width="@dimen/header_icon_width"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="6dip"
android:layout_marginRight="6dip"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="6dip"
android:layout_marginEnd="6dip"
android:layout_marginStart="2dip"
android:layout_marginTop="6dip"
android:layout_weight="1">
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<TextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@android:id/summary"
android:layout_below="@android:id/title"
android:ellipsize="end"
android:maxLines="2"
android:textAppearance="?android:attr/textAppearanceSmall"/>
</RelativeLayout>
</LinearLayout>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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/>.
-->
<!-- Layout of a header item in PreferenceActivity. -->
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="?android:colorBackground"
app:cardCornerRadius="0dp"
app:cardElevation="4dp">
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:padding="@dimen/element_spacing_normal"
android:singleLine="true"
android:textAllCaps="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textStyle="bold"/>
</android.support.v7.widget.CardView>

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2012 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Layout of a header item in PreferenceActivity. -->
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="?android:colorBackground"
app:cardCornerRadius="0dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:selectableItemBackground"
android:gravity="center_vertical"
android:minHeight="?android:listPreferredItemHeight"
android:orientation="horizontal">
<ImageView
android:id="@android:id/icon"
android:layout_width="@dimen/header_icon_width"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="@dimen/element_spacing_large"
android:layout_marginRight="@dimen/element_spacing_large"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="6dip"
android:layout_marginEnd="6dip"
android:layout_marginStart="2dip"
android:layout_marginTop="6dip"
android:layout_weight="1">
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<TextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@android:id/summary"
android:layout_below="@android:id/title"
android:ellipsize="end"
android:maxLines="2"
android:textAppearance="?android:attr/textAppearanceSmall"/>
</RelativeLayout>
</LinearLayout>
</android.support.v7.widget.CardView>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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/>.
-->
<Space xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/element_spacing_normal"/>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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/>.
-->
<transitionSet
xmlns:android="http://schemas.android.com/apk/res/android">
<fade>
<targets>
<target android:targetId="@id/card"/>
</targets>
</fade>
</transitionSet>

View File

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Widget.CardActionButton" parent="android:Widget.DeviceDefault.ImageButton">
<style name="Widget.CardActionButton" parent="Widget.Base.ImageButton">
<item name="android:background">?android:selectableItemBackgroundBorderless</item>
</style>
<style name="Widget.Light.CardActionButton" parent="android:Widget.DeviceDefault.ImageButton">
<style name="Widget.Light.CardActionButton" parent="Widget.Base.ImageButton">
<item name="android:background">?android:selectableItemBackgroundBorderless</item>
</style>
@ -21,7 +21,7 @@
<item name="borderWidth">2dp</item>
</style>
<style name="Widget.ProfileType" parent="android:Widget.DeviceDefault">
<style name="Widget.ProfileType" parent="Widget.Base">
<item name="android:elevation">@dimen/elevation_card</item>
<item name="android:outlineProvider">none</item>
</style>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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/>.
-->
<resources>
<style name="Widget.Base" parent="android:Widget.Material"/>
<style name="Widget.Base.ActionButton.Overflow" parent="android:Widget.Material.ActionButton.Overflow"/>
<style name="Widget.Base.ActionButton" parent="android:Widget.Material.ActionButton"/>
<style name="Widget.Base.Light.ActionButton.Overflow" parent="android:Widget.Material.Light.ActionButton.Overflow"/>
<style name="Widget.Base.Light.ActionButton" parent="android:Widget.Material.Light.ActionButton"/>
<style name="Widget.Base.Light" parent="android:Widget.Material.Light"/>
<style name="Widget.Base.Light.ImageButton" parent="android:Widget.Material.Light.ImageButton"/>
<style name="Widget.Base.ImageButton" parent="android:Widget.Material.ImageButton"/>
<style name="Widget.Base.ActionBar" parent="android:Widget.Material.ActionBar"/>
<style name="Widget.Base.ActionBar.Solid" parent="android:Widget.Material.ActionBar.Solid"/>
<style name="Widget.Base.Light.ActionBar.Solid" parent="android:Widget.Material.Light.ActionBar.Solid"/>
<style name="Widget.Base.Light.ActionBar.Solid.Inverse" parent="android:Widget.Holo.Light.ActionBar.Solid.Inverse"/>
</resources>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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/>.
-->
<resources>
<style name="Theme.Base" parent="android:Theme.Material"/>
<style name="Theme.Base.NoActionBar" parent="android:Theme.Material.NoActionBar"/>
<style name="Theme.Base.Dialog" parent="android:Theme.Material.Dialog"/>
<style name="Theme.Base.Light" parent="android:Theme.Material.Light"/>
<style name="Theme.Base.Light.DarkActionBar" parent="android:Theme.Material.Light.DarkActionBar"/>
<style name="Theme.Base.Light.Dialog" parent="android:Theme.Material.Light.Dialog"/>
</resources>

View File

@ -678,5 +678,7 @@
<string name="profile_banner">Profile banner</string>
<string name="profile">Profile</string>
<string name="listed">Listed</string>
<string name="state_blocking">Blocking</string>
<string name="load_more">Load more</string>
</resources>

View File

@ -1,65 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Widget.Twidere.ActionBar.Colored" parent="android:Widget.DeviceDefault.Light.ActionBar.Solid">
<style name="Widget.Twidere.ActionBar.Colored" parent="Widget.Base.Light.ActionBar.Solid">
<item name="android:background">@drawable/ab_twidere_solid_color_holo</item>
<!--<item name="android:background">@android:color/transparent</item>-->
</style>
<style name="Widget.Twidere.ActionBar.Colored.Inverse" parent="android:Widget.DeviceDefault.Light.ActionBar.Solid.Inverse">
<style name="Widget.Twidere.ActionBar.Colored.Inverse" parent="Widget.Base.Light.ActionBar.Solid.Inverse">
<item name="android:background">@drawable/ab_twidere_solid_color_holo</item>
<!--<item name="android:background">@android:color/transparent</item>-->
</style>
<style name="Widget.Twidere.ActionBar.Dark" parent="android:Widget.DeviceDefault.ActionBar.Solid">
<style name="Widget.Twidere.ActionBar.Dark" parent="Widget.Base.ActionBar.Solid">
<item name="android:background">@drawable/ab_twidere_solid_dark_holo</item>
<!--<item name="android:background">@android:color/transparent</item>-->
</style>
<style name="Widget.Twidere.ActionBar.Light" parent="android:Widget.DeviceDefault.Light.ActionBar.Solid">
<style name="Widget.Twidere.ActionBar.Light" parent="Widget.Base.Light.ActionBar.Solid">
<item name="android:background">@drawable/ab_twidere_solid_light_holo</item>
<!--<item name="android:background">@android:color/transparent</item>-->
</style>
<style name="Widget.Twidere.ActionBar.Light.DarkActionBar" parent="android:Widget.DeviceDefault.Light.ActionBar.Solid.Inverse">
<style name="Widget.Twidere.ActionBar.Light.DarkActionBar" parent="Widget.Base.Light.ActionBar.Solid.Inverse">
<item name="android:background">@drawable/ab_twidere_solid_dark_holo</item>
<!--<item name="android:background">@android:color/transparent</item>-->
</style>
<style name="Widget.Twidere.Viewer.ActionBar" parent="android:Widget.DeviceDefault.ActionBar">
<style name="Widget.Twidere.Viewer.ActionBar" parent="Widget.Base.ActionBar">
<item name="android:background">#80000000</item>
<item name="android:backgroundSplit">#80000000</item>
</style>
<style name="Widget.Twidere.ImageButton.Borderless" parent="android:Widget.DeviceDefault.ImageButton">
<style name="Widget.Twidere.ImageButton.Borderless" parent="Widget.Base.ImageButton">
<item name="android:background">?android:attr/selectableItemBackground</item>
</style>
<style name="Widget.Twidere.Light.ImageButton.Borderless" parent="android:Widget.DeviceDefault.Light.ImageButton">
<style name="Widget.Twidere.Light.ImageButton.Borderless" parent="Widget.Base.Light.ImageButton">
<item name="android:background">?android:attr/selectableItemBackground</item>
</style>
<style name="Widget.Twidere.SelectableView" parent="android:Widget.DeviceDefault">
<style name="Widget.Twidere.SelectableView" parent="Widget.Base">
<item name="android:background">?android:attr/selectableItemBackground</item>
</style>
<style name="Widget.Twidere.Light.SelectableView" parent="android:Widget.DeviceDefault.Light">
<style name="Widget.Twidere.Light.SelectableView" parent="Widget.Base.Light">
<item name="android:background">?android:attr/selectableItemBackground</item>
</style>
<style name="Widget.Twidere.ActionButton.Colored" parent="android:Widget.DeviceDefault.Light.ActionButton">
<style name="Widget.Twidere.ActionButton.Colored" parent="Widget.Base.Light.ActionButton">
<item name="android:background">?android:actionBarItemBackground</item>
</style>
<style name="Widget.Twidere.ActionButton.Overflow.Colored" parent="android:Widget.DeviceDefault.Light.ActionButton.Overflow">
<style name="Widget.Twidere.ActionButton.Overflow.Colored" parent="Widget.Base.Light.ActionButton.Overflow">
<item name="android:background">?android:actionBarItemBackground</item>
</style>
<style name="Widget.Twidere.ActionButton.Colored.DarkActionBar" parent="android:Widget.DeviceDefault.ActionButton">
<style name="Widget.Twidere.ActionButton.Colored.DarkActionBar" parent="Widget.Base.ActionButton">
<item name="android:background">?android:actionBarItemBackground</item>
</style>
<style name="Widget.Twidere.ActionButton.Overflow.Colored.DarkActionBar" parent="android:Widget.DeviceDefault.ActionButton.Overflow">
<style name="Widget.Twidere.ActionButton.Overflow.Colored.DarkActionBar" parent="Widget.Base.ActionButton.Overflow">
<item name="android:background">?android:actionBarItemBackground</item>
</style>
@ -118,7 +118,7 @@
<item name="scrimAlpha">0.75</item>
</style>
<style name="Widget.CardItemView" parent="android:Widget.DeviceDefault">
<style name="Widget.CardItemView" parent="Widget.Base">
<item name="cardBackground">?cardItemBackground</item>
<item name="cardBackgroundAlpha">50%p</item>
<item name="cardSelector">?android:selectableItemBackground</item>
@ -130,7 +130,7 @@
<item name="cardGapTextSize">18sp</item>
</style>
<style name="Widget.CardItemView.Light" parent="android:Widget.DeviceDefault">
<style name="Widget.CardItemView.Light" parent="Widget.Base">
<item name="cardBackground">?cardItemBackground</item>
<item name="cardBackgroundAlpha">50%p</item>
<item name="cardSelector">?android:selectableItemBackground</item>
@ -142,26 +142,26 @@
<item name="cardGapTextSize">18sp</item>
</style>
<style name="Widget.StaggeredGridView" parent="android:Widget.DeviceDefault">
<style name="Widget.StaggeredGridView" parent="Widget.Base">
<item name="column_count_portrait">@integer/staggered_grid_columns_port</item>
<item name="column_count_landscape">@integer/staggered_grid_columns_land</item>
</style>
<style name="Widget.CardActionButton" parent="android:Widget.DeviceDefault.ImageButton">
<style name="Widget.CardActionButton" parent="Widget.Base.ImageButton">
<item name="android:background">?android:selectableItemBackground</item>
</style>
<style name="Widget.Light.CardActionButton" parent="android:Widget.DeviceDefault.Light.ImageButton">
<style name="Widget.Light.CardActionButton" parent="Widget.Base.Light.ImageButton">
<item name="android:background">?android:selectableItemBackground</item>
</style>
<style name="Widget.ProfileImage" parent="android:Widget.DeviceDefault">
<style name="Widget.ProfileImage" parent="Widget.Base">
<item name="android:scaleType">centerCrop</item>
<item name="borderWidth">1dp</item>
</style>
<style name="Widget.Light.ProfileImage" parent="android:Widget.DeviceDefault">
<style name="Widget.Light.ProfileImage" parent="Widget.Base">
<item name="android:scaleType">centerCrop</item>
<item name="borderWidth">1dp</item>
</style>
@ -186,6 +186,6 @@
<item name="borderWidth">2dp</item>
</style>
<style name="Widget.ProfileType" parent="android:Widget.DeviceDefault">
<style name="Widget.ProfileType" parent="Widget.Base">
</style>
</resources>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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/>.
-->
<resources>
<style name="Widget.Base" parent="android:Widget.Holo"/>
<style name="Widget.Base.ActionButton.Overflow" parent="android:Widget.Holo.ActionButton.Overflow"/>
<style name="Widget.Base.ActionButton" parent="android:Widget.Holo.ActionButton"/>
<style name="Widget.Base.Light.ActionButton.Overflow" parent="android:Widget.Holo.Light.ActionButton.Overflow"/>
<style name="Widget.Base.Light.ActionButton" parent="android:Widget.Holo.Light.ActionButton"/>
<style name="Widget.Base.Light" parent="android:Widget.Holo.Light"/>
<style name="Widget.Base.Light.ImageButton" parent="android:Widget.Holo.Light.ImageButton"/>
<style name="Widget.Base.ImageButton" parent="android:Widget.Holo.ImageButton"/>
<style name="Widget.Base.ActionBar" parent="android:Widget.Holo.ActionBar"/>
<style name="Widget.Base.ActionBar.Solid" parent="android:Widget.Holo.ActionBar.Solid"/>
<style name="Widget.Base.Light.ActionBar.Solid" parent="android:Widget.Holo.Light.ActionBar.Solid"/>
<style name="Widget.Base.Light.ActionBar.Solid.Inverse" parent="android:Widget.Holo.Light.ActionBar.Solid.Inverse"/>
</resources>

View File

@ -7,16 +7,16 @@
<item name="android:windowAnimationStyle">@android:style/Animation.Activity</item>
</style>
<style name="Theme.Blank" parent="android:Theme.DeviceDefault.NoActionBar">
<style name="Theme.Blank" parent="Theme.Base.NoActionBar">
<!-- Window attributes -->
<!--<item name="android:windowAnimationStyle">@style/Animation.Twidere.Activity</item>-->
<item name="android:windowBackground">@android:color/black</item>
</style>
<style name="Theme.Blank.Dialog" parent="android:Theme.DeviceDefault.Dialog"/>
<style name="Theme.Blank.Dialog" parent="Theme.Base.Dialog"/>
<style name="Theme.Twidere.Dark" parent="android:Theme.DeviceDefault">
<style name="Theme.Twidere.Dark" parent="Theme.Base">
<!-- Colors -->
<!--<item name="android:colorBackgroundCacheHint">@color/bg_color_dark</item>-->
@ -64,7 +64,7 @@
<item name="messageBubbleColor">@color/message_bubble_color_dark</item>
</style>
<style name="Theme.Twidere.Light" parent="android:Theme.DeviceDefault.Light.DarkActionBar">
<style name="Theme.Twidere.Light" parent="Theme.Base.Light.DarkActionBar">
<!-- Colors -->
<!--<item name="android:colorBackgroundCacheHint">@color/bg_color_light</item>-->
@ -155,7 +155,7 @@
<!--<item name="android:actionBarItemBackground">@drawable/list_selector_white</item>-->
</style>
<style name="Theme.Twidere.Dark.Dialog" parent="android:Theme.DeviceDefault.Dialog">
<style name="Theme.Twidere.Dark.Dialog" parent="Theme.Base.Dialog">
<!-- Custom view styles -->
<item name="tabItemStyle">@style/Widget.TabPageIndicator.TabItem</item>
@ -190,7 +190,7 @@
<item name="messageBubbleColor">@color/message_bubble_color_dark</item>
</style>
<style name="Theme.Twidere.Light.Dialog" parent="android:Theme.DeviceDefault.Light.Dialog">
<style name="Theme.Twidere.Light.Dialog" parent="Theme.Base.Light.Dialog">
<!-- Custom view styles -->
<item name="tabItemStyle">@style/Widget.TabPageIndicator.TabItem</item>
@ -251,7 +251,7 @@
<item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
</style>
<style name="Theme.Twidere.Viewer" parent="android:Theme.DeviceDefault">
<style name="Theme.Twidere.Viewer" parent="Theme.Base">
<!-- Window attributes -->
<item name="android:windowActionBarOverlay">true</item>
@ -321,7 +321,7 @@
<!-- Window attributes -->
</style>
<style name="Theme.Twidere.Dark.NoDisplay" parent="android:Theme.DeviceDefault">
<style name="Theme.Twidere.Dark.NoDisplay" parent="Theme.Base">
<item name="android:windowBackground">@null</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowIsTranslucent">true</item>
@ -330,7 +330,7 @@
<item name="android:windowNoDisplay">true</item>
</style>
<style name="Theme.Twidere.Light.NoDisplay" parent="android:Theme.DeviceDefault.Light">
<style name="Theme.Twidere.Light.NoDisplay" parent="Theme.Base.Light">
<item name="android:windowBackground">@null</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowIsTranslucent">true</item>
@ -339,16 +339,16 @@
<item name="android:windowNoDisplay">true</item>
</style>
<style name="Theme.Test" parent="android:Theme.DeviceDefault">
<style name="Theme.Test" parent="Theme.Base">
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowActionModeOverlay">true</item>
</style>
<style name="Theme.Nyan" parent="android:Theme.DeviceDefault.NoActionBar">
<style name="Theme.Nyan" parent="Theme.Base.NoActionBar">
<item name="android:windowBackground">@color/nyan_background</item>
</style>
<style name="Theme.Twidere.Settings.Dark" parent="android:Theme.DeviceDefault">
<style name="Theme.Twidere.Settings.Dark" parent="Theme.Base">
<!-- Colors -->
<item name="android:colorBackgroundCacheHint">@color/bg_color_dark</item>
@ -393,7 +393,7 @@
<item name="messageBubbleColor">@color/message_bubble_color_dark</item>
</style>
<style name="Theme.Twidere.Settings.Light" parent="android:Theme.DeviceDefault.Light">
<style name="Theme.Twidere.Settings.Light" parent="Theme.Base.Light">
<!-- Colors -->
<item name="android:colorBackgroundCacheHint">@color/bg_color_light</item>
@ -434,7 +434,7 @@
<item name="messageBubbleColor">@color/message_bubble_color_light</item>
</style>
<style name="Theme.Twidere.Settings.Light.DarkActionBar" parent="android:Theme.DeviceDefault.Light.DarkActionBar">
<style name="Theme.Twidere.Settings.Light.DarkActionBar" parent="Theme.Base.Light.DarkActionBar">
<!-- Colors -->
<!--<item name="android:colorBackgroundCacheHint">@color/bg_color_light</item>-->

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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/>.
-->
<resources>
<style name="Theme.Base" parent="android:Theme.Holo"/>
<style name="Theme.Base.NoActionBar" parent="android:Theme.Holo.NoActionBar"/>
<style name="Theme.Base.Dialog" parent="android:Theme.Holo.Dialog"/>
<style name="Theme.Base.Light" parent="android:Theme.Holo.Light"/>
<style name="Theme.Base.Light.DarkActionBar" parent="android:Theme.Holo.Light.DarkActionBar"/>
<style name="Theme.Base.Light.Dialog" parent="android:Theme.Holo.Light.Dialog"/>
</resources>

View File

@ -1,99 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:title="@string/cards">
xmlns:app="http://schemas.android.com/apk/res-auto"
android:title="@string/cards">
<PreferenceCategory
android:key="cat_card_preview"
android:order="11"
android:title="@string/preview">
<org.mariotaku.twidere.preference.CardPreviewPreference android:key="card_preview"/>
</PreferenceCategory>
<PreferenceCategory
android:key="cat_card_preview"
android:order="11"
android:title="@string/preview">
<org.mariotaku.twidere.preference.CardPreviewPreference android:key="card_preview"/>
</PreferenceCategory>
<org.mariotaku.twidere.preference.SeekBarDialogPreference
android:defaultValue="@integer/default_text_size"
android:key="text_size_int"
android:order="21"
android:summary="@string/text_size_summary"
android:title="@string/text_size"
app:max="24"
app:min="12"
app:progressTextSuffix="sp"/>
<org.mariotaku.twidere.preference.SeekBarDialogPreference
android:defaultValue="@integer/default_text_size"
android:key="text_size_int"
android:order="21"
android:summary="@string/text_size_summary"
android:title="@string/text_size"
app:max="24"
app:min="12"
app:progressTextSuffix="sp"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="true"
android:key="name_first"
android:order="22"
android:title="@string/name_first"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="false"
android:key="nickname_only"
android:order="23"
android:summary="@string/nickname_only_summary"
android:title="@string/nickname_only"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="true"
android:key="display_profile_image"
android:order="24"
android:summary="@string/image_load_summary"
android:title="@string/display_profile_image"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="false"
android:key="display_image_preview"
android:order="25"
android:summary="@string/image_load_summary"
android:title="@string/display_image_preview"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="true"
android:key="name_first"
android:order="22"
android:title="@string/name_first"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="false"
android:key="nickname_only"
android:order="23"
android:summary="@string/nickname_only_summary"
android:title="@string/nickname_only"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="true"
android:key="display_profile_image"
android:order="24"
android:summary="@string/image_load_summary"
android:title="@string/display_profile_image"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="false"
android:key="display_image_preview"
android:order="25"
android:summary="@string/image_load_summary"
android:title="@string/display_image_preview"/>
<org.mariotaku.twidere.preference.AutoFixListPreference
android:defaultValue="CENTER_CROP"
android:entries="@array/entries_image_preview_scale_type"
android:entryValues="@array/values_image_preview_scale_type"
android:key="image_preview_scale_type"
android:order="26"
android:summary="%s"
android:title="@string/image_preview_scale_type"/>
<org.mariotaku.twidere.preference.AutoFixListPreference
android:defaultValue="CENTER_CROP"
android:entries="@array/entries_image_preview_scale_type"
android:entryValues="@array/values_image_preview_scale_type"
android:key="image_preview_scale_type"
android:order="26"
android:summary="%s"
android:title="@string/image_preview_scale_type"/>
<org.mariotaku.twidere.preference.LinkHighlightPreference
android:defaultValue="none"
android:key="link_highlight_option"
android:order="27"
android:title="@string/link_highlight_option"/>
<org.mariotaku.twidere.preference.LinkHighlightPreference
android:defaultValue="none"
android:key="link_highlight_option"
android:order="27"
android:title="@string/link_highlight_option"/>
<org.mariotaku.twidere.preference.AutoInvalidateListPreference
android:defaultValue="background"
android:entries="@array/entries_card_highlight_option"
android:entryValues="@array/values_card_highlight_option"
android:key="card_highlight_option"
android:order="28"
android:summary="%s"
android:title="@string/card_highlight_option"/>
<org.mariotaku.twidere.preference.AutoInvalidateListPreference
android:defaultValue="background"
android:entries="@array/entries_card_highlight_option"
android:entryValues="@array/values_card_highlight_option"
android:key="card_highlight_option"
android:order="28"
android:summary="%s"
android:title="@string/card_highlight_option"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="true"
android:key="indicate_my_status"
android:order="29"
android:title="@string/indicate_your_status"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="false"
android:key="show_absolute_time"
android:order="30"
android:summary="@string/show_absolute_time_summary"
android:title="@string/show_absolute_time"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="true"
android:key="card_animation"
android:order="31"
android:title="@string/card_animation"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="false"
android:key="compact_cards"
android:order="32"
android:summary="@string/compact_cards_summary"
android:title="@string/compact_cards"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="false"
android:key="plain_list_style"
android:order="33"
android:title="@string/plain_list_style"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="true"
android:key="indicate_my_status"
android:order="29"
android:title="@string/indicate_your_status"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="false"
android:key="show_absolute_time"
android:order="30"
android:summary="@string/show_absolute_time_summary"
android:title="@string/show_absolute_time"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="true"
android:key="card_animation"
android:order="31"
android:title="@string/card_animation"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="false"
android:key="compact_cards"
android:order="32"
android:summary="@string/compact_cards_summary"
android:title="@string/compact_cards"/>
</PreferenceScreen>