removed unused resource

improved favorite feature
improving tab indicator
This commit is contained in:
Mariotaku Lee 2014-12-12 21:53:18 +08:00
parent 8d18bdf844
commit a31cde86a1
81 changed files with 1240 additions and 3531 deletions

View File

@ -92,7 +92,6 @@ dependencies {
compile 'org.apache.httpcomponents:httpclient-android:4.3.5' compile 'org.apache.httpcomponents:httpclient-android:4.3.5'
compile 'org.apache.httpcomponents:httpmime:4.3.5' compile 'org.apache.httpcomponents:httpmime:4.3.5'
compile 'com.google.android.apps.dashclock:dashclock-api:2.0.0' compile 'com.google.android.apps.dashclock:dashclock-api:2.0.0'
compile 'com.astuetz:pagerslidingtabstrip:1.0.1'
compile 'com.squareup:otto:1.3.5' compile 'com.squareup:otto:1.3.5'
googleCompile 'com.google.android.gms:play-services:6.5.87' googleCompile 'com.google.android.gms:play-services:6.5.87'
fdroidCompile 'org.osmdroid:osmdroid-android:4.2' fdroidCompile 'org.osmdroid:osmdroid-android:4.2'

View File

@ -532,13 +532,11 @@ public class HomeActivity extends BaseSupportActivity implements OnClickListener
mTabIndicator.setViewPager(mViewPager); mTabIndicator.setViewPager(mViewPager);
mTabIndicator.setOnPageChangeListener(this); mTabIndicator.setOnPageChangeListener(this);
if (mTabDisplayOption != 0) { if (mTabDisplayOption != 0) {
mTabIndicator.setDisplayLabel((mTabDisplayOption & VALUE_TAB_DIPLAY_OPTION_CODE_LABEL) != 0); mTabIndicator.setTabDisplayOption(mTabDisplayOption);
mTabIndicator.setDisplayIcon((mTabDisplayOption & VALUE_TAB_DIPLAY_OPTION_CODE_ICON) != 0);
} else { } else {
mTabIndicator.setDisplayLabel(false); mTabIndicator.setTabDisplayOption(TabPagerIndicator.ICON);
mTabIndicator.setDisplayIcon(true);
} }
// mTabIndicator.setDisplayBadge(mPreferences.getBoolean(KEY_UNREAD_COUNT, true)); mTabIndicator.setDisplayBadge(mPreferences.getBoolean(KEY_UNREAD_COUNT, true));
mActionsButton.setOnClickListener(this); mActionsButton.setOnClickListener(this);
mActionsButton.setOnLongClickListener(this); mActionsButton.setOnLongClickListener(this);
setTabPosition(initialTabPosition); setTabPosition(initialTabPosition);

View File

@ -16,6 +16,7 @@ import org.mariotaku.twidere.adapter.iface.IStatusesAdapter;
import org.mariotaku.twidere.app.TwidereApplication; import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.fragment.support.UserFragment; import org.mariotaku.twidere.fragment.support.UserFragment;
import org.mariotaku.twidere.model.ParcelableStatus; import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.ImageLoaderWrapper; import org.mariotaku.twidere.util.ImageLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler; import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.Utils; import org.mariotaku.twidere.util.Utils;
@ -38,15 +39,18 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
private final ImageLoaderWrapper mImageLoader; private final ImageLoaderWrapper mImageLoader;
private final ImageLoadingHandler mLoadingHandler; private final ImageLoadingHandler mLoadingHandler;
private final int mCardLayoutResource; private final int mCardLayoutResource;
private final AsyncTwitterWrapper mTwitterWrapper;
private boolean mLoadMoreIndicatorEnabled; private boolean mLoadMoreIndicatorEnabled;
private StatusAdapterListener mStatusAdapterListener; private StatusAdapterListener mStatusAdapterListener;
public AbsStatusesAdapter(Context context, boolean compact) { public AbsStatusesAdapter(Context context, boolean compact) {
mContext = context; mContext = context;
final TwidereApplication app = TwidereApplication.getInstance(context);
mInflater = LayoutInflater.from(context); mInflater = LayoutInflater.from(context);
mImageLoader = TwidereApplication.getInstance(context).getImageLoaderWrapper(); mImageLoader = app.getImageLoaderWrapper();
mLoadingHandler = new ImageLoadingHandler(R.id.media_preview_progress); mLoadingHandler = new ImageLoadingHandler(R.id.media_preview_progress);
mTwitterWrapper = app.getTwitterWrapper();
if (compact) { if (compact) {
mCardLayoutResource = R.layout.card_item_status_compat; mCardLayoutResource = R.layout.card_item_status_compat;
} else { } else {
@ -54,62 +58,13 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
} }
} }
@Override public abstract D getData();
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case ITEM_VIEW_TYPE_STATUS: {
final View view = mInflater.inflate(mCardLayoutResource, parent, false);
final StatusViewHolder holder = new StatusViewHolder(this, view);
holder.setupViews();
return holder;
}
case ITEM_VIEW_TYPE_GAP: {
final View view = mInflater.inflate(R.layout.card_item_gap, parent, false);
return new GapViewHolder(this, view);
}
case ITEM_VIEW_TYPE_LOAD_INDICATOR: {
final View view = mInflater.inflate(R.layout.card_item_load_indicator, parent, false);
return new LoadIndicatorViewHolder(view);
}
}
throw new IllegalStateException("Unknown view type " + viewType);
}
public void setLoadMoreIndicatorEnabled(boolean enabled) { public abstract void setData(D data);
if (mLoadMoreIndicatorEnabled == enabled) return;
mLoadMoreIndicatorEnabled = enabled;
notifyDataSetChanged();
}
public boolean hasLoadMoreIndicator() {
return mLoadMoreIndicatorEnabled;
}
@Override @Override
public void onBindViewHolder(ViewHolder holder, int position) { public AsyncTwitterWrapper getTwitterWrapper() {
switch (holder.getItemViewType()) { return mTwitterWrapper;
case ITEM_VIEW_TYPE_STATUS: {
bindStatus(((StatusViewHolder) holder), position);
break;
}
}
}
protected abstract void bindStatus(StatusViewHolder holder, int position);
@Override
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;
}
@Override
public final int getItemCount() {
return getStatusCount() + (mLoadMoreIndicatorEnabled ? 1 : 0);
} }
@Override @Override
@ -150,6 +105,63 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
} }
} }
public boolean hasLoadMoreIndicator() {
return mLoadMoreIndicatorEnabled;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case ITEM_VIEW_TYPE_STATUS: {
final View view = mInflater.inflate(mCardLayoutResource, parent, false);
final StatusViewHolder holder = new StatusViewHolder(this, view);
holder.setupViews();
return holder;
}
case ITEM_VIEW_TYPE_GAP: {
final View view = mInflater.inflate(R.layout.card_item_gap, parent, false);
return new GapViewHolder(this, view);
}
case ITEM_VIEW_TYPE_LOAD_INDICATOR: {
final View view = mInflater.inflate(R.layout.card_item_load_indicator, parent, false);
return new LoadIndicatorViewHolder(view);
}
}
throw new IllegalStateException("Unknown view type " + viewType);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case ITEM_VIEW_TYPE_STATUS: {
bindStatus(((StatusViewHolder) holder), position);
break;
}
}
}
@Override
public int getItemViewType(int position) {
if (position == getItemCount() - 1) {
return ITEM_VIEW_TYPE_LOAD_INDICATOR;
} else if (isGapItem(position)) {
return ITEM_VIEW_TYPE_GAP;
}
return ITEM_VIEW_TYPE_STATUS;
}
@Override
public final int getItemCount() {
return getStatusCount() + (mLoadMoreIndicatorEnabled ? 1 : 0);
}
@Override
public final void onGapClick(ViewHolder holder, int position) {
if (mStatusAdapterListener != null) {
mStatusAdapterListener.onGapClick((GapViewHolder) holder, position);
}
}
@Override @Override
public void onItemActionClick(ViewHolder holder, int id, int position) { public void onItemActionClick(ViewHolder holder, int id, int position) {
if (mStatusAdapterListener != null) { if (mStatusAdapterListener != null) {
@ -164,28 +176,25 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
} }
} }
public abstract void setData(D data);
public abstract D getData();
public void setEventListener(StatusAdapterListener listener) { public void setEventListener(StatusAdapterListener listener) {
mStatusAdapterListener = listener; mStatusAdapterListener = listener;
} }
@Override public void setLoadMoreIndicatorEnabled(boolean enabled) {
public final void onGapClick(ViewHolder holder, int position) { if (mLoadMoreIndicatorEnabled == enabled) return;
if (mStatusAdapterListener != null) { mLoadMoreIndicatorEnabled = enabled;
mStatusAdapterListener.onGapClick((GapViewHolder) holder, position); notifyDataSetChanged();
}
} }
protected abstract void bindStatus(StatusViewHolder holder, int position);
public static interface StatusAdapterListener { public static interface StatusAdapterListener {
void onGapClick(GapViewHolder holder, int position);
void onStatusActionClick(StatusViewHolder holder, int id, int position); void onStatusActionClick(StatusViewHolder holder, int id, int position);
void onStatusClick(StatusViewHolder holder, int position); void onStatusClick(StatusViewHolder holder, int position);
void onGapClick(GapViewHolder holder, int position);
void onStatusMenuClick(StatusViewHolder holder, int position); void onStatusMenuClick(StatusViewHolder holder, int position);
} }

View File

@ -24,6 +24,7 @@ import android.database.Cursor;
import org.mariotaku.twidere.model.ParcelableStatus; import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatus.CursorIndices; import org.mariotaku.twidere.model.ParcelableStatus.CursorIndices;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.view.holder.StatusViewHolder; import org.mariotaku.twidere.view.holder.StatusViewHolder;
/** /**
@ -72,7 +73,6 @@ public class CursorStatusesAdapter extends AbsStatusesAdapter<Cursor> {
mIndices = data != null ? new CursorIndices(data) : null; mIndices = data != null ? new CursorIndices(data) : null;
notifyDataSetChanged(); notifyDataSetChanged();
} }
@Override @Override
public Cursor getData() { public Cursor getData() {
return mCursor; return mCursor;

View File

@ -1,347 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.adapter;
import android.app.Activity;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.widget.RecyclerView.ViewHolder;
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.model.ParcelableStatus;
import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.MultiSelectManager;
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.util.Utils.configBaseCardAdapter;
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 ParcelableStatusesListAdapter extends BaseArrayAdapter<ParcelableStatus> implements
IStatusesListAdapter<List<ParcelableStatus>>, OnClickListener, OnOverflowIconClickListener {
private final Context mContext;
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 ScaleType mImagePreviewScaleType;
private String[] mHighlightKeywords;
public ParcelableStatusesListAdapter(final Context context) {
this(context, Utils.isCompactCards(context));
}
public ParcelableStatusesListAdapter(final Context context, final boolean compactCards) {
super(context, getItemResource(compactCards));
mContext = context;
final TwidereApplication app = TwidereApplication.getInstance(context);
mMultiSelectManager = app.getMultiSelectManager();
mDatabase = app.getSQLiteDatabase();
mImageLoadingHandler = new ImageLoadingHandler();
configBaseCardAdapter(context, this);
setMaxAnimationPosition(-1);
}
@Override
public int findPositionByStatusId(final long status_id) {
for (int i = 0, count = getCount(); i < count; i++) {
if (getItem(i).id == status_id) return i;
}
return -1;
}
@Override
public long getAccountId(final int position) {
if (position >= 0 && position < getCount()) {
final ParcelableStatus status = getItem(position);
return status != null ? status.account_id : -1;
}
return -1;
}
@Override
public int getStatusCount() {
return super.getCount();
}
@Override
public void onItemActionClick(ViewHolder holder, int id, int position) {
}
@Override
public void onItemMenuClick(ViewHolder 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 long getItemId(final int position) {
final ParcelableStatus item = getItem(position);
return item != null ? item.id : -1;
}
@Override
public ParcelableStatus getLastStatus() {
if (super.getCount() == 0) return null;
return getItem(super.getCount() - 1);
}
@Override
public long getLastStatusId() {
if (super.getCount() == 0) return -1;
return getItem(super.getCount() - 1).id;
}
@Override
public ImageLoadingHandler getImageLoadingHandler() {
return mImageLoadingHandler;
}
@Override
public ParcelableStatus getStatus(final int position) {
return getItem(position);
}
@Override
public long getStatusId(final int position) {
if (position >= 0 && position < getCount()) {
final ParcelableStatus status = getItem(position);
return status != null ? status.id : -1;
}
return -1;
}
@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 StatusViewHolder holder;
if (tag instanceof StatusViewHolder) {
holder = (StatusViewHolder) tag;
} else {
holder = new StatusViewHolder(this, view);
view.setTag(holder);
}
final ParcelableStatus status = getItem(position);
holder.displayStatus(status);
return view;
}
@Override
public boolean isGapItem(int position) {
return false;
}
@Override
public void onGapClick(ViewHolder holder, int position) {
}
@Override
public boolean isLastItemFiltered() {
return mIsLastItemFiltered;
}
@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;
if (mContext instanceof Activity) {
openUserProfile(mContext, status.account_id, status.user_id,
status.user_screen_name, null);
}
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 List<ParcelableStatus> data) {
clear();
if (data != null && !data.isEmpty()) {
addAll(data);
}
rebuildFilterInfo();
}
@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();
}
@Override
public void setGapDisallowed(final boolean disallowed) {
mGapDisallowed = disallowed;
}
@Override
public void setHighlightKeyword(final String... keywords) {
mHighlightKeywords = keywords;
}
@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();
}
@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;
}
private void rebuildFilterInfo() {
if (!isEmpty()) {
final ParcelableStatus last = getItem(super.getCount() - 1);
final long user_id = mFilterIgnoreUser ? -1 : last.user_id;
final String text_plain = mFilterIgnoreTextPlain ? null : last.text_plain;
final String text_html = mFilterIgnoreTextHtml ? null : last.text_html;
final String source = mFilterIgnoreSource ? null : last.source;
final long retweeted_by_id = mFilterRetweetedById ? -1 : last.retweeted_by_id;
mIsLastItemFiltered = isFiltered(mDatabase, user_id, text_plain, text_html, source, retweeted_by_id);
} else {
mIsLastItemFiltered = false;
}
notifyDataSetChanged();
}
private static int getItemResource(final boolean compactCards) {
return compactCards ? R.layout.card_item_status_compat : R.layout.card_item_status;
}
}

View File

@ -1,157 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import org.mariotaku.twidere.R;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
public class SeparatedListAdapter<T extends Adapter> extends BaseAdapter {
private final Map<String, T> mSections = new LinkedHashMap<String, T>();
private final ArrayAdapter<String> mHeaders;
private final static int TYPE_SECTION_HEADER = 0;
public SeparatedListAdapter(final Context context) {
mHeaders = new ArrayAdapter<String>(context, R.layout.list_item_section_header);
}
public void addSection(final String section, final T adapter) {
mHeaders.add(section);
mSections.put(section, adapter);
notifyDataSetChanged();
}
public boolean areAllItemsSelectable() {
return false;
}
public void clear() {
mHeaders.clear();
mSections.clear();
notifyDataSetChanged();
}
public ArrayList<T> getAdapters() {
return new ArrayList<T>(mSections.values());
}
@Override
public int getCount() {
// total together all sections, plus one for each section header
int total = 0;
for (final T adapter : mSections.values()) {
total += adapter.getCount() + 1;
}
return total;
}
@Override
public Object getItem(int position) {
for (final Object section : mSections.keySet()) {
final Adapter adapter = mSections.get(section);
final int size = adapter.getCount() + 1;
// check if position inside this section
if (position == 0) return section;
if (position < size) return adapter.getItem(position - 1);
// otherwise jump into next section
position -= size;
}
return null;
}
@Override
public long getItemId(final int position) {
return position;
}
@Override
public int getItemViewType(int position) {
int type = 1;
for (final Object section : mSections.keySet()) {
final Adapter adapter = mSections.get(section);
final int size = adapter.getCount() + 1;
// check if position inside this section
if (position == 0) return TYPE_SECTION_HEADER;
if (position < size) return type + adapter.getItemViewType(position - 1);
// otherwise jump into next section
position -= size;
type += adapter.getViewTypeCount();
}
return -1;
}
@Override
public View getView(int position, final View convertView, final ViewGroup parent) {
int sectionnum = 0;
for (final Object section : mSections.keySet()) {
final Adapter adapter = mSections.get(section);
final int size = adapter.getCount() + 1;
// check if position inside this section
if (position == 0) return mHeaders.getView(sectionnum, convertView, parent);
if (position < size) return adapter.getView(position - 1, convertView, parent);
// otherwise jump into next section
position -= size;
sectionnum++;
}
return null;
}
@Override
public int getViewTypeCount() {
// assume that headers count as one, then total all sections
int total = 1;
for (final Adapter adapter : mSections.values()) {
total += adapter.getViewTypeCount();
}
return total;
}
@Override
public boolean isEnabled(final int position) {
return getItemViewType(position) != TYPE_SECTION_HEADER;
}
@Override
public void notifyDataSetChanged() {
for (final T adapter : mSections.values()) {
if (adapter instanceof BaseAdapter) {
((BaseAdapter) adapter).notifyDataSetChanged();
}
}
super.notifyDataSetChanged();
}
}

View File

@ -3,6 +3,7 @@ package org.mariotaku.twidere.adapter.iface;
import android.content.Context; import android.content.Context;
import org.mariotaku.twidere.model.ParcelableStatus; import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.ImageLoaderWrapper; import org.mariotaku.twidere.util.ImageLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler; import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.view.holder.StatusViewHolder; import org.mariotaku.twidere.view.holder.StatusViewHolder;
@ -27,4 +28,6 @@ public interface IStatusesAdapter<Data> extends IGapSupportedAdapter, ICardSuppo
void onUserProfileClick(StatusViewHolder holder, int position); void onUserProfileClick(StatusViewHolder holder, int position);
void setData(Data data); void setData(Data data);
AsyncTwitterWrapper getTwitterWrapper();
} }

View File

@ -18,6 +18,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.squareup.otto.Bus; import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import org.mariotaku.twidere.R; import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.AbsStatusesAdapter; import org.mariotaku.twidere.adapter.AbsStatusesAdapter;
@ -31,6 +32,7 @@ import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.SimpleDrawerCallback; import org.mariotaku.twidere.util.SimpleDrawerCallback;
import org.mariotaku.twidere.util.ThemeUtils; import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.Utils; import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.message.StatusListChangedEvent;
import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback; import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback;
import org.mariotaku.twidere.view.holder.GapViewHolder; import org.mariotaku.twidere.view.holder.GapViewHolder;
import org.mariotaku.twidere.view.holder.StatusViewHolder; import org.mariotaku.twidere.view.holder.StatusViewHolder;
@ -41,6 +43,13 @@ import org.mariotaku.twidere.view.holder.StatusViewHolder;
public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment implements LoaderCallbacks<Data>, public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment implements LoaderCallbacks<Data>,
OnRefreshListener, DrawerCallback, RefreshScrollTopInterface, StatusAdapterListener { OnRefreshListener, DrawerCallback, RefreshScrollTopInterface, StatusAdapterListener {
private final Object mStatusesBusCallback;
protected AbsStatusesFragment() {
mStatusesBusCallback = createMessageBusCallback();
}
private View mContentView; private View mContentView;
private SharedPreferences mPreferences; private SharedPreferences mPreferences;
private View mProgressContainer; private View mProgressContainer;
@ -151,19 +160,13 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus(); final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
final Object callback = getMessageBusCallback(); bus.register(mStatusesBusCallback);
if (callback != null) {
bus.register(callback);
}
} }
@Override @Override
public void onStop() { public void onStop() {
final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus(); final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus();
final Object callback = getMessageBusCallback(); bus.unregister(mStatusesBusCallback);
if (callback != null) {
bus.unregister(callback);
}
super.onStop(); super.onStop();
} }
@ -273,8 +276,8 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
mAdapter.setData(data); mAdapter.setData(data);
} }
protected Object getMessageBusCallback() { protected Object createMessageBusCallback() {
return null; return new StatusesBusCallback();
} }
protected abstract AbsStatusesAdapter<Data> onCreateAdapter(Context context, boolean compact); protected abstract AbsStatusesAdapter<Data> onCreateAdapter(Context context, boolean compact);
@ -285,4 +288,17 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
mProgressContainer.setVisibility(shown ? View.GONE : View.VISIBLE); mProgressContainer.setVisibility(shown ? View.GONE : View.VISIBLE);
mSwipeRefreshLayout.setVisibility(shown ? View.VISIBLE : View.GONE); mSwipeRefreshLayout.setVisibility(shown ? View.VISIBLE : View.GONE);
} }
protected final class StatusesBusCallback {
protected StatusesBusCallback() {
}
@Subscribe
public void notifyStatusListChanged(StatusListChangedEvent event) {
mAdapter.notifyDataSetChanged();
}
}
} }

View File

@ -1,592 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.fragment.support;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import android.support.v4.util.LongSparseArray;
import android.util.Log;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ImageView.ScaleType;
import android.widget.ListView;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.iface.IBaseCardAdapter.MenuButtonClickListener;
import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableAccount.ParcelableAccountWithCredentials;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.task.TwidereAsyncTask;
import org.mariotaku.twidere.util.AsyncTaskManager;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.ClipboardUtils;
import org.mariotaku.twidere.util.MultiSelectManager;
import org.mariotaku.twidere.util.PositionManager;
import org.mariotaku.twidere.util.TwitterWrapper;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.collection.NoDuplicatesCopyOnWriteArrayList;
import org.mariotaku.twidere.view.holder.StatusListViewHolder;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.mariotaku.twidere.util.Utils.clearListViewChoices;
import static org.mariotaku.twidere.util.Utils.configBaseCardAdapter;
import static org.mariotaku.twidere.util.Utils.isMyRetweet;
import static org.mariotaku.twidere.util.Utils.openStatus;
import static org.mariotaku.twidere.util.Utils.showOkMessage;
import static org.mariotaku.twidere.util.Utils.startStatusShareChooser;
abstract class BaseStatusesListFragment<Data> extends BasePullToRefreshListFragment implements LoaderCallbacks<Data>,
OnItemLongClickListener, OnMenuItemClickListener, MultiSelectManager.Callback, MenuButtonClickListener {
private AsyncTaskManager mAsyncTaskManager;
private SharedPreferences mPreferences;
private ListView mListView;
private IStatusesListAdapter<Data> mAdapter;
private Data mData;
private ParcelableStatus mSelectedStatus;
private boolean mLoadMoreAutomatically;
private int mListScrollOffset;
private MultiSelectManager mMultiSelectManager;
private PositionManager mPositionManager;
private int mFirstVisibleItem;
private int mSelectedPosition;
private final LongSparseArray<Set<Long>> mUnreadCountsToRemove = new LongSparseArray<>();
private final List<Integer> mReadPositions = new NoDuplicatesCopyOnWriteArrayList<>();
private RemoveUnreadCountsTask<Data> mRemoveUnreadCountsTask;
public AsyncTaskManager getAsyncTaskManager() {
return mAsyncTaskManager;
}
public final Data getData() {
return mData;
}
@Override
public IStatusesListAdapter<Data> getListAdapter() {
return mAdapter;
}
public ParcelableStatus getSelectedStatus() {
return mSelectedStatus;
}
public SharedPreferences getSharedPreferences() {
return mPreferences;
}
public abstract int getStatuses(long[] account_ids, long[] max_ids, long[] since_ids);
public final LongSparseArray<Set<Long>> getUnreadCountsToRemove() {
return mUnreadCountsToRemove;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final Context context = getActivity();
mAsyncTaskManager = getAsyncTaskManager();
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
mPositionManager = new PositionManager(context);
mMultiSelectManager = getMultiSelectManager();
mListView = getListView();
final boolean compactCards = mPreferences.getBoolean(KEY_COMPACT_CARDS, false);
mAdapter = newAdapterInstance(compactCards);
mAdapter.setMenuButtonClickListener(this);
setListAdapter(null);
setListHeaderFooters(mListView);
setListAdapter(mAdapter);
if (!compactCards) {
mListView.setDivider(null);
}
mListView.setSelector(android.R.color.transparent);
mListView.setOnItemLongClickListener(this);
setListShown(false);
getLoaderManager().initLoader(0, getArguments(), this);
}
@Override
public abstract Loader<Data> onCreateLoader(int id, Bundle args);
@Override
public boolean onItemLongClick(final AdapterView<?> parent, final View view, final int position, final long id) {
final Object tag = view.getTag();
if (tag instanceof StatusListViewHolder) {
final StatusListViewHolder holder = (StatusListViewHolder) tag;
final ParcelableStatus status = mAdapter.getStatus(position - mListView.getHeaderViewsCount());
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter != null) {
TwitterWrapper.removeUnreadCounts(getActivity(), getTabPosition(), status.account_id, status.id);
}
if (holder.show_as_gap) return false;
if (mPreferences.getBoolean(KEY_LONG_CLICK_TO_OPEN_MENU, false)) {
openMenu(holder.content.getFakeOverflowButton(), status, position);
} else {
setItemSelected(status, position, !mMultiSelectManager.isSelected(status));
}
return true;
}
return false;
}
@Override
public void onItemsCleared() {
clearListViewChoices(mListView);
}
@Override
public void onItemSelected(final Object item) {
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}
@Override
public void onItemUnselected(final Object item) {
}
@Override
public void onListItemClick(final ListView l, final View v, final int position, final long id) {
final Object tag = v.getTag();
if (tag instanceof StatusListViewHolder) {
final int pos = position - l.getHeaderViewsCount();
final ParcelableStatus status = mAdapter.getStatus(pos);
if (status == null) return;
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter != null) {
TwitterWrapper.removeUnreadCounts(getActivity(), getTabPosition(), status.account_id, status.id);
}
if (((StatusListViewHolder) tag).show_as_gap) {
final long since_id = position + 1 < mAdapter.getStatusCount() ? mAdapter.getStatus(pos + 1).id : -1;
getStatuses(new long[]{status.account_id}, new long[]{status.id}, new long[]{since_id});
mListView.setItemChecked(position, false);
} else {
if (mMultiSelectManager.isActive()) {
setItemSelected(status, position, !mMultiSelectManager.isSelected(status));
return;
}
openStatus(getActivity(), status.account_id, status.id);
}
}
}
@Override
public final void onLoaderReset(final Loader<Data> loader) {
mAdapter.setData(mData = null);
}
@Override
public void onLoadFinished(final Loader<Data> loader, final Data data) {
if (getActivity() == null || getView() == null) return;
setListShown(true);
setRefreshComplete();
setProgressBarIndeterminateVisibility(false);
setData(data);
mFirstVisibleItem = -1;
mReadPositions.clear();
final int firstVisiblePosition = mListView.getFirstVisiblePosition();
final int lastVisiblePosition = mListView.getLastVisiblePosition();
final int listVisiblePosition, savedChildIndex;
final boolean rememberPosition = mPreferences.getBoolean(KEY_REMEMBER_POSITION, true);
final boolean loadMoreFromTop = mPreferences.getBoolean(KEY_LOAD_MORE_FROM_TOP, false);
final int childCount = mListView.getChildCount();
if (firstVisiblePosition != 0 && lastVisiblePosition != mListView.getCount() - 1 && loadMoreFromTop) {
listVisiblePosition = lastVisiblePosition;
savedChildIndex = childCount - 1;
if (childCount > 0) {
final View lastChild = mListView.getChildAt(savedChildIndex);
mListScrollOffset = lastChild != null ? lastChild.getTop() - mListView.getListPaddingTop() : 0;
}
} else {
listVisiblePosition = firstVisiblePosition;
savedChildIndex = 0;
if (childCount > 0) {
final View firstChild = mListView.getChildAt(savedChildIndex);
mListScrollOffset = firstChild != null ? firstChild.getTop() - mListView.getListPaddingTop() : 0;
}
}
final long lastViewedId = mAdapter.getStatusId(listVisiblePosition);
mAdapter.setData(data);
mAdapter.setShowAccountColor(shouldShowAccountColor());
final int currFirstVisiblePosition = mListView.getFirstVisiblePosition();
final long currViewedId = mAdapter.getStatusId(currFirstVisiblePosition);
final long statusId;
if (lastViewedId <= 0) {
if (!rememberPosition) return;
statusId = mPositionManager.getPosition(getPositionKey());
} else if ((listVisiblePosition > 0 || rememberPosition) && currViewedId > 0 && lastViewedId != currViewedId) {
statusId = lastViewedId;
} else {
if (listVisiblePosition == 0 && mAdapter.getStatusId(0) != lastViewedId) {
mAdapter.setMaxAnimationPosition(mListView.getLastVisiblePosition());
}
return;
}
final int position = mAdapter.findPositionByStatusId(statusId);
if (position > -1 && position < mListView.getCount()) {
mAdapter.setMaxAnimationPosition(mListView.getLastVisiblePosition());
mListView.setSelectionFromTop(position, mListScrollOffset);
mListScrollOffset = 0;
}
}
@Override
public void onMenuButtonClick(final View button, final int position, final long id) {
if (mMultiSelectManager.isActive()) return;
final ParcelableStatus status = mAdapter.getStatus(position);
if (status == null) return;
openMenu(button, status, position);
}
@Override
public final boolean onMenuItemClick(final MenuItem item) {
final ParcelableStatus status = mSelectedStatus;
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (status == null || twitter == null) return false;
switch (item.getItemId()) {
case MENU_VIEW: {
openStatus(getActivity(), status, null);
break;
}
case MENU_SHARE: {
startStatusShareChooser(getActivity(), status);
break;
}
case MENU_COPY: {
if (ClipboardUtils.setText(getActivity(), status.text_plain)) {
showOkMessage(getActivity(), R.string.text_copied, false);
}
break;
}
case MENU_RETWEET: {
if (isMyRetweet(status)) {
twitter.cancelRetweetAsync(status.account_id, status.id, status.my_retweet_id);
} else {
twitter.retweetStatusAsync(status.account_id, status.id);
}
break;
}
case MENU_QUOTE: {
final Intent intent = new Intent(INTENT_ACTION_QUOTE);
final Bundle bundle = new Bundle();
bundle.putParcelable(EXTRA_STATUS, status);
intent.putExtras(bundle);
startActivity(intent);
break;
}
case MENU_REPLY: {
final Intent intent = new Intent(INTENT_ACTION_REPLY);
final Bundle bundle = new Bundle();
bundle.putParcelable(EXTRA_STATUS, status);
intent.putExtras(bundle);
startActivity(intent);
break;
}
case MENU_FAVORITE: {
if (status.is_favorite) {
twitter.destroyFavoriteAsync(status.account_id, status.id);
} else {
twitter.createFavoriteAsync(status.account_id, status.id);
}
break;
}
case MENU_DELETE: {
DestroyStatusDialogFragment.show(getFragmentManager(), status);
break;
}
case MENU_ADD_TO_FILTER: {
AddStatusFilterDialogFragment.show(getFragmentManager(), status);
break;
}
case MENU_TRANSLATE: {
final ParcelableAccountWithCredentials account = ParcelableAccount.getAccountWithCredentials(getActivity(),
status.account_id);
if (ParcelableAccountWithCredentials.isOfficialCredentials(getActivity(), account)) {
StatusTranslateDialogFragment.show(getFragmentManager(), status);
} else {
}
break;
}
case MENU_MULTI_SELECT: {
final boolean isSelected = !mMultiSelectManager.isSelected(status);
setItemSelected(status, mSelectedPosition, isSelected);
break;
}
default: {
if (item.getIntent() != null) {
try {
startActivity(item.getIntent());
} catch (final ActivityNotFoundException e) {
Log.w(LOGTAG, e);
return false;
}
}
break;
}
}
return true;
}
@Override
public void onRefreshFromEnd() {
if (mLoadMoreAutomatically) return;
loadMoreStatuses();
}
@Override
public void onResume() {
super.onResume();
mListView.setFastScrollEnabled(mPreferences.getBoolean(KEY_FAST_SCROLL_THUMB, false));
configBaseCardAdapter(getActivity(), mAdapter);
final boolean displayImagePreview = mPreferences.getBoolean(KEY_DISPLAY_IMAGE_PREVIEW, false);
final boolean displaySensitiveContents = mPreferences.getBoolean(KEY_DISPLAY_SENSITIVE_CONTENTS, false);
final boolean indicateMyStatus = mPreferences.getBoolean(KEY_INDICATE_MY_STATUS, true);
final String cardHighlightOption = mPreferences.getString(KEY_CARD_HIGHLIGHT_OPTION,
DEFAULT_CARD_HIGHLIGHT_OPTION);
final String previewScaleType = Utils.getNonEmptyString(mPreferences, KEY_IMAGE_PREVIEW_SCALE_TYPE,
ScaleType.CENTER_CROP.name());
mAdapter.setDisplayImagePreview(displayImagePreview);
mAdapter.setImagePreviewScaleType(previewScaleType);
mAdapter.setDisplaySensitiveContents(displaySensitiveContents);
mAdapter.setIndicateMyStatusDisabled(isMyTimeline() || !indicateMyStatus);
mAdapter.setCardHighlightOption(cardHighlightOption);
mAdapter.notifyDataSetChanged();
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 onScrollStateChanged(final AbsListView view, final int scrollState) {
super.onScrollStateChanged(view, scrollState);
switch (scrollState) {
case SCROLL_STATE_IDLE:
for (int i = mListView.getFirstVisiblePosition(), j = mListView.getLastVisiblePosition(); i < j; i++) {
mReadPositions.add(i);
}
removeUnreadCounts();
break;
default:
break;
}
}
@Override
public void onStart() {
super.onStart();
mMultiSelectManager.registerCallback(this);
final int choiceMode = mListView.getChoiceMode();
if (mMultiSelectManager.isActive()) {
if (choiceMode != ListView.CHOICE_MODE_MULTIPLE) {
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}
} else {
if (choiceMode != ListView.CHOICE_MODE_NONE) {
Utils.clearListViewChoices(mListView);
}
}
updateRefreshState();
}
@Override
public void onStop() {
savePosition();
mMultiSelectManager.unregisterCallback(this);
super.onStop();
}
@Override
public boolean scrollToStart() {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
final int tab_position = getTabPosition();
if (twitter != null && tab_position >= 0) {
twitter.clearUnreadCountAsync(tab_position);
}
return super.scrollToStart();
}
@Override
public void setUserVisibleHint(final boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
updateRefreshState();
}
protected final int getListScrollOffset() {
return mListScrollOffset;
}
protected abstract long[] getNewestStatusIds();
protected abstract long[] getOldestStatusIds();
protected abstract String getPositionKey();
protected boolean isMyTimeline() {
return false;
}
protected abstract void loadMoreStatuses();
protected abstract IStatusesListAdapter<Data> newAdapterInstance(boolean compact);
@Override
protected void onReachedBottom() {
if (!mLoadMoreAutomatically) return;
loadMoreStatuses();
}
protected void savePosition() {
final int first_visible_position = mListView.getFirstVisiblePosition();
if (mListView.getChildCount() > 0) {
final View first_child = mListView.getChildAt(0);
mListScrollOffset = first_child != null ? first_child.getTop() : 0;
}
final long status_id = mAdapter.getStatusId(first_visible_position);
mPositionManager.setPosition(getPositionKey(), status_id);
}
protected final void setData(final Data data) {
mData = data;
}
protected void setItemSelected(final ParcelableStatus status, final int position, final boolean selected) {
if (selected) {
mMultiSelectManager.selectItem(status);
} else {
mMultiSelectManager.unselectItem(status);
}
if (position >= 0) {
mListView.setItemChecked(position, selected);
}
}
protected void setListHeaderFooters(final ListView list) {
}
protected boolean shouldEnablePullToRefresh() {
return true;
}
protected abstract boolean shouldShowAccountColor();
protected abstract void updateRefreshState();
private void addReadPosition(final int firstVisibleItem) {
if (mFirstVisibleItem != firstVisibleItem) {
mReadPositions.add(firstVisibleItem);
}
mFirstVisibleItem = firstVisibleItem;
}
private void addUnreadCountsToRemove(final long accountId, final long id) {
if (mUnreadCountsToRemove.indexOfKey(accountId) < 0) {
final Set<Long> counts = new HashSet<>();
counts.add(id);
mUnreadCountsToRemove.put(accountId, counts);
} else {
final Set<Long> counts = mUnreadCountsToRemove.get(accountId);
counts.add(id);
}
}
private void openMenu(final View view, final ParcelableStatus status, final int position) {
mSelectedStatus = status;
mSelectedPosition = position;
final FragmentActivity activity = getActivity();
if (activity == null || activity.isFinishing() || view == null || status == null) return;
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter != null) {
TwitterWrapper.removeUnreadCounts(getActivity(), getTabPosition(), status.account_id, status.id);
}
final StatusMenuDialogFragment df = new StatusMenuDialogFragment();
final Bundle args = new Bundle();
args.putParcelable(EXTRA_STATUS, status);
df.setArguments(args);
df.show(getChildFragmentManager(), "status_menu");
}
private void removeUnreadCounts() {
if (mRemoveUnreadCountsTask != null && mRemoveUnreadCountsTask.getStatus() == TwidereAsyncTask.Status.RUNNING)
return;
mRemoveUnreadCountsTask = new RemoveUnreadCountsTask<Data>(mReadPositions, this);
mRemoveUnreadCountsTask.executeTask();
}
static class RemoveUnreadCountsTask<T> extends TwidereAsyncTask<Void, Void, Void> {
private final List<Integer> read_positions;
private final IStatusesListAdapter<T> adapter;
private final BaseStatusesListFragment<T> fragment;
RemoveUnreadCountsTask(final List<Integer> read_positions, final BaseStatusesListFragment<T> fragment) {
this.read_positions = read_positions;
this.fragment = fragment;
this.adapter = fragment.getListAdapter();
}
@Override
protected Void doInBackground(final Void... params) {
for (final int pos : read_positions) {
final long id = adapter.getStatusId(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());
}
}
}
}

View File

@ -32,6 +32,7 @@ import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.message.FavoriteCreatedEvent; import org.mariotaku.twidere.util.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.util.message.FavoriteDestroyedEvent; import org.mariotaku.twidere.util.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.util.message.StatusDestroyedEvent; import org.mariotaku.twidere.util.message.StatusDestroyedEvent;
import org.mariotaku.twidere.util.message.StatusListChangedEvent;
import org.mariotaku.twidere.util.message.StatusRetweetedEvent; import org.mariotaku.twidere.util.message.StatusRetweetedEvent;
import java.util.HashSet; import java.util.HashSet;
@ -43,11 +44,6 @@ import java.util.Set;
*/ */
public abstract class ParcelableStatusesFragment extends AbsStatusesFragment<List<ParcelableStatus>> { public abstract class ParcelableStatusesFragment extends AbsStatusesFragment<List<ParcelableStatus>> {
private final StatusesBusCallback mStatusesBusCallback;
protected ParcelableStatusesFragment() {
mStatusesBusCallback = new StatusesBusCallback(this);
}
public final void deleteStatus(final long statusId) { public final void deleteStatus(final long statusId) {
final List<ParcelableStatus> data = getAdapterData(); final List<ParcelableStatus> data = getAdapterData();
@ -98,8 +94,8 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment<Lis
} }
@Override @Override
protected Object getMessageBusCallback() { protected Object createMessageBusCallback() {
return mStatusesBusCallback; return new ParcelableStatusesBusCallback();
} }
@Override @Override
@ -155,36 +151,6 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment<Lis
} }
} }
protected static class StatusesBusCallback {
private final ParcelableStatusesFragment fragment;
StatusesBusCallback(ParcelableStatusesFragment fragment) {
this.fragment = fragment;
}
@Subscribe
public void notifyFavoriteCreated(FavoriteCreatedEvent event) {
fragment.updateFavoritedStatus(event.status);
}
@Subscribe
public void notifyStatusRetweeted(StatusRetweetedEvent event) {
fragment.updateRetweetedStatuses(event.status);
}
@Subscribe
public void notifyFavoriteDestroyed(FavoriteDestroyedEvent event) {
fragment.updateFavoritedStatus(event.status);
}
@Subscribe
public void notifyStatusDestroyed(StatusDestroyedEvent event) {
fragment.deleteStatus(event.status.id);
}
}
private void updateRetweetedStatuses(ParcelableStatus status) { private void updateRetweetedStatuses(ParcelableStatus status) {
final List<ParcelableStatus> data = getAdapterData(); final List<ParcelableStatus> data = getAdapterData();
if (status == null || status.retweet_id <= 0 || data == null) return; if (status == null || status.retweet_id <= 0 || data == null) return;
@ -197,4 +163,33 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment<Lis
setAdapterData(data); setAdapterData(data);
} }
protected class ParcelableStatusesBusCallback {
@Subscribe
public void notifyFavoriteCreated(FavoriteCreatedEvent event) {
updateFavoritedStatus(event.status);
}
@Subscribe
public void notifyFavoriteDestroyed(FavoriteDestroyedEvent event) {
updateFavoritedStatus(event.status);
}
@Subscribe
public void notifyStatusDestroyed(StatusDestroyedEvent event) {
deleteStatus(event.status.id);
}
@Subscribe
public void notifyStatusListChanged(StatusListChangedEvent event) {
getAdapter().notifyDataSetChanged();
}
@Subscribe
public void notifyStatusRetweeted(StatusRetweetedEvent event) {
updateRetweetedStatuses(event.status);
}
}
} }

View File

@ -1,222 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.fragment.support;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import org.mariotaku.twidere.adapter.ParcelableStatusesListAdapter;
import org.mariotaku.twidere.adapter.iface.IStatusesListAdapter;
import org.mariotaku.twidere.loader.support.DummyParcelableStatusesLoader;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.ArrayUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static org.mariotaku.twidere.util.Utils.encodeQueryParams;
public abstract class ParcelableStatusesListFragment extends BaseStatusesListFragment<List<ParcelableStatus>> {
protected SharedPreferences mPreferences;
private boolean mStatusesRestored;
private boolean mIsFirstCreated;
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();
switch (action) {
// case BROADCAST_STATUS_RETWEETED: {
// final long status_id = intent.getLongExtra(EXTRA_STATUS_ID, -1);
// final boolean retweeted = intent.getBooleanExtra(EXTRA_RETWEETED, false);
// if (status_id > 0 && !retweeted) {
// deleteStatus(status_id);
// }
// break;
// }
case BROADCAST_MULTI_MUTESTATE_CHANGED: {
final Bundle args = getArguments();
final long account_id = args != null ? args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
if (account_id <= 0) return;
getStatuses(new long[]{account_id}, null, null);
break;
}
}
}
};
public final void deleteStatus(final long status_id) {
final List<ParcelableStatus> data = getData();
if (status_id <= 0 || data == null) return;
final ArrayList<ParcelableStatus> data_to_remove = new ArrayList<ParcelableStatus>();
for (final ParcelableStatus status : data) {
if (status.id == status_id || status.retweet_id > 0 && status.retweet_id == status_id) {
data_to_remove.add(status);
}
}
data.removeAll(data_to_remove);
getListAdapter().setData(data);
}
@Override
public final int getStatuses(final long[] accountIds, final long[] maxIds, final long[] sinceIds) {
mStatusesRestored = true;
final long maxId = maxIds != null && maxIds.length == 1 ? maxIds[0] : -1;
final long sinceId = sinceIds != null && sinceIds.length == 1 ? sinceIds[0] : -1;
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 onActivityCreated(final Bundle savedInstanceState) {
mStatusesRestored = false;
if (savedInstanceState != null) {
final List<ParcelableStatus> saved = savedInstanceState.getParcelableArrayList(EXTRA_DATA);
if (saved != null) {
setData(saved);
}
}
super.onActivityCreated(savedInstanceState);
mPreferences = getSharedPreferences();
mIsFirstCreated = savedInstanceState == null;
}
@Override
public final Loader<List<ParcelableStatus>> onCreateLoader(final int id, final Bundle args) {
setProgressBarIndeterminateVisibility(true);
final List<ParcelableStatus> data = getData();
if (isInstanceStateSaved() && data != null && !mStatusesRestored)
return new DummyParcelableStatusesLoader(getActivity(), data);
final Loader<List<ParcelableStatus>> loader = newLoaderInstance(getActivity(), args);
return loader != null ? loader : new DummyParcelableStatusesLoader(getActivity());
}
@Override
public void onLoadFinished(final Loader<List<ParcelableStatus>> loader, final List<ParcelableStatus> data) {
super.onLoadFinished(loader, data);
if (mIsFirstCreated && mPreferences.getBoolean(KEY_REFRESH_ON_START, false)) {
onRefreshFromStart();
}
}
@Override
public void onRefreshFromStart() {
if (isRefreshing()) return;
final IStatusesListAdapter<List<ParcelableStatus>> adapter = getListAdapter();
final int count = adapter.getCount();
final ParcelableStatus status = count > 0 ? adapter.getStatus(0) : null;
if (status != null) {
getStatuses(new long[]{status.account_id}, null, new long[]{status.id});
} else {
getStatuses(null, null, null);
}
}
@Override
public void onSaveInstanceState(final Bundle outState) {
final List<ParcelableStatus> data = getData();
if (data != null) {
outState.putParcelableArrayList(EXTRA_DATA, new ArrayList<>(data));
}
super.onSaveInstanceState(outState);
}
@Override
public void onStart() {
super.onStart();
}
@Override
public void onStop() {
super.onStop();
}
@Override
protected final long[] getNewestStatusIds() {
final IStatusesListAdapter<List<ParcelableStatus>> adapter = getListAdapter();
final long last_id = adapter.getCount() > 0 ? adapter.getStatus(0).id : -1;
return last_id > 0 ? new long[]{last_id} : null;
}
@Override
protected final long[] getOldestStatusIds() {
final IStatusesListAdapter<List<ParcelableStatus>> adapter = getListAdapter();
final ParcelableStatus status = adapter.getLastStatus();
final long last_id = status != null ? status.id : -1;
return last_id > 0 ? new long[]{last_id} : null;
}
@Override
protected final String getPositionKey() {
final Object[] args = getSavedStatusesFileArgs();
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[] getSavedStatusesFileArgs();
@Override
protected void loadMoreStatuses() {
if (isRefreshing()) return;
final IStatusesListAdapter<List<ParcelableStatus>> adapter = getListAdapter();
final ParcelableStatus status = adapter.getLastStatus();
if (status != null) {
getStatuses(new long[]{status.account_id}, new long[]{status.id}, null);
}
}
@Override
protected ParcelableStatusesListAdapter newAdapterInstance(final boolean compact) {
return new ParcelableStatusesListAdapter(getActivity(), compact);
}
protected abstract Loader<List<ParcelableStatus>> newLoaderInstance(Context context, Bundle args);
@Override
protected void updateRefreshState() {
if (getActivity() == null || !getUserVisibleHint() || !isVisible()) return;
final LoaderManager lm = getLoaderManager();
final boolean hasRunningLoaders = lm.hasRunningLoaders();
if (!hasRunningLoaders) {
setRefreshing(true);
}
setRefreshing(hasRunningLoaders);
}
}

View File

@ -72,6 +72,7 @@ public class RetweetQuoteDialogFragment extends BaseSupportDialogFragment implem
final Context context = builder.getContext(); final Context context = builder.getContext();
final ImageLoaderWrapper loader = TwidereApplication.getInstance(context).getImageLoaderWrapper(); final ImageLoaderWrapper loader = TwidereApplication.getInstance(context).getImageLoaderWrapper();
final ImageLoadingHandler handler = new ImageLoadingHandler(R.id.media_preview_progress); final ImageLoadingHandler handler = new ImageLoadingHandler(R.id.media_preview_progress);
final AsyncTwitterWrapper twitter = getTwitterWrapper();
final LayoutInflater inflater = LayoutInflater.from(context); final LayoutInflater inflater = LayoutInflater.from(context);
@SuppressLint("InflateParams") final View view = inflater.inflate(R.layout.dialog_scrollable_status, null); @SuppressLint("InflateParams") final View view = inflater.inflate(R.layout.dialog_scrollable_status, null);
final StatusViewHolder holder = new StatusViewHolder(view.findViewById(R.id.item_content)); final StatusViewHolder holder = new StatusViewHolder(view.findViewById(R.id.item_content));
@ -85,7 +86,7 @@ public class RetweetQuoteDialogFragment extends BaseSupportDialogFragment implem
builder.setNegativeButton(android.R.string.cancel, null); builder.setNegativeButton(android.R.string.cancel, null);
holder.displayStatus(context, loader, handler, getStatus()); holder.displayStatus(context, loader, handler, twitter, getStatus());
view.findViewById(R.id.item_menu).setVisibility(View.GONE); view.findViewById(R.id.item_menu).setVisibility(View.GONE);
view.findViewById(R.id.action_buttons).setVisibility(View.GONE); view.findViewById(R.id.action_buttons).setVisibility(View.GONE);
view.findViewById(R.id.reply_retweet_status).setVisibility(View.GONE); view.findViewById(R.id.reply_retweet_status).setVisibility(View.GONE);

View File

@ -33,8 +33,6 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.astuetz.PagerSlidingTabStrip;
import org.mariotaku.twidere.R; import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.support.LinkHandlerActivity; import org.mariotaku.twidere.activity.support.LinkHandlerActivity;
import org.mariotaku.twidere.adapter.support.SupportTabsAdapter; import org.mariotaku.twidere.adapter.support.SupportTabsAdapter;
@ -43,6 +41,7 @@ import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface;
import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback; import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback;
import org.mariotaku.twidere.provider.RecentSearchProvider; import org.mariotaku.twidere.provider.RecentSearchProvider;
import org.mariotaku.twidere.util.AsyncTwitterWrapper; import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.view.TabPagerIndicator;
public class SearchFragment extends BaseSupportFragment implements RefreshScrollTopInterface, public class SearchFragment extends BaseSupportFragment implements RefreshScrollTopInterface,
SupportFragmentCallback, SystemWindowsInsetsCallback { SupportFragmentCallback, SystemWindowsInsetsCallback {
@ -50,7 +49,7 @@ public class SearchFragment extends BaseSupportFragment implements RefreshScroll
private ViewPager mViewPager; private ViewPager mViewPager;
private SupportTabsAdapter mAdapter; private SupportTabsAdapter mAdapter;
private PagerSlidingTabStrip mPagerIndicator; private TabPagerIndicator mPagerIndicator;
private Fragment mCurrentVisibleFragment; private Fragment mCurrentVisibleFragment;
@ -141,7 +140,7 @@ public class SearchFragment extends BaseSupportFragment implements RefreshScroll
public void onViewCreated(final View view, final Bundle savedInstanceState) { public void onViewCreated(final View view, final Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
mViewPager = (ViewPager) view.findViewById(R.id.view_pager); mViewPager = (ViewPager) view.findViewById(R.id.view_pager);
mPagerIndicator = (PagerSlidingTabStrip) view.findViewById(R.id.view_pager_tabs); mPagerIndicator = (TabPagerIndicator) view.findViewById(R.id.view_pager_tabs);
} }
@Override @Override

View File

@ -438,6 +438,11 @@ public class StatusFragment extends BaseSupportFragment
} }
@Override
public AsyncTwitterWrapper getTwitterWrapper() {
return mFragment.getTwitterWrapper();
}
public ParcelableStatus getStatus() { public ParcelableStatus getStatus() {
return mStatus; return mStatus;
} }

View File

@ -71,7 +71,6 @@ import android.widget.ImageView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import com.astuetz.PagerSlidingTabStrip;
import com.squareup.otto.Bus; import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
@ -113,6 +112,7 @@ import org.mariotaku.twidere.view.CircularImageView;
import org.mariotaku.twidere.view.HeaderDrawerLayout; import org.mariotaku.twidere.view.HeaderDrawerLayout;
import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback; import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback;
import org.mariotaku.twidere.view.ProfileBannerImageView; import org.mariotaku.twidere.view.ProfileBannerImageView;
import org.mariotaku.twidere.view.TabPagerIndicator;
import org.mariotaku.twidere.view.TintedStatusFrameLayout; import org.mariotaku.twidere.view.TintedStatusFrameLayout;
import org.mariotaku.twidere.view.iface.IColorLabelView; import org.mariotaku.twidere.view.iface.IColorLabelView;
import org.mariotaku.twidere.view.iface.IExtendedView.OnSizeChangedListener; import org.mariotaku.twidere.view.iface.IExtendedView.OnSizeChangedListener;
@ -180,7 +180,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
private TintedStatusFrameLayout mTintedStatusContent; private TintedStatusFrameLayout mTintedStatusContent;
private HeaderDrawerLayout mHeaderDrawerLayout; private HeaderDrawerLayout mHeaderDrawerLayout;
private ViewPager mViewPager; private ViewPager mViewPager;
private PagerSlidingTabStrip mPagerIndicator; private TabPagerIndicator mPagerIndicator;
private CardView mCardView; private CardView mCardView;
private View mUuckyFooter; private View mUuckyFooter;
private View mProfileBannerContainer; private View mProfileBannerContainer;
@ -617,6 +617,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
mViewPager.setOffscreenPageLimit(3); mViewPager.setOffscreenPageLimit(3);
mViewPager.setAdapter(mPagerAdapter); mViewPager.setAdapter(mPagerAdapter);
mPagerIndicator.setViewPager(mViewPager); mPagerIndicator.setViewPager(mViewPager);
mPagerIndicator.setTabDisplayOption(TabPagerIndicator.LABEL);
mFollowButton.setOnClickListener(this); mFollowButton.setOnClickListener(this);
mProfileImageView.setOnClickListener(this); mProfileImageView.setOnClickListener(this);
@ -853,7 +854,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
mURLContainer = headerView.findViewById(R.id.url_container); mURLContainer = headerView.findViewById(R.id.url_container);
mProfileBannerSpace = headerView.findViewById(R.id.profile_banner_space); mProfileBannerSpace = headerView.findViewById(R.id.profile_banner_space);
mViewPager = (ViewPager) contentView.findViewById(R.id.view_pager); mViewPager = (ViewPager) contentView.findViewById(R.id.view_pager);
mPagerIndicator = (PagerSlidingTabStrip) contentView.findViewById(R.id.view_pager_tabs); mPagerIndicator = (TabPagerIndicator) contentView.findViewById(R.id.view_pager_tabs);
mFollowButton = (Button) headerView.findViewById(R.id.follow); mFollowButton = (Button) headerView.findViewById(R.id.follow);
mFollowProgress = (ProgressBar) headerView.findViewById(R.id.follow_progress); mFollowProgress = (ProgressBar) headerView.findViewById(R.id.follow_progress);
mUuckyFooter = headerView.findViewById(R.id.uucky_footer); mUuckyFooter = headerView.findViewById(R.id.uucky_footer);
@ -1143,7 +1144,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
} }
mActionBarBackground.setColor(color); mActionBarBackground.setColor(color);
mTintedStatusContent.setColor(color, ThemeUtils.getThemeAlpha(getActivity())); mTintedStatusContent.setColor(color, ThemeUtils.getThemeAlpha(getActivity()));
mPagerIndicator.setIndicatorColor(color); mPagerIndicator.setStripColor(color);
} }
private void setupUserPages() { private void setupUserPages() {
@ -1161,12 +1162,11 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
tabArgs.putLong(EXTRA_USER_ID, args.getLong(EXTRA_USER_ID, -1)); tabArgs.putLong(EXTRA_USER_ID, args.getLong(EXTRA_USER_ID, -1));
tabArgs.putString(EXTRA_SCREEN_NAME, args.getString(EXTRA_SCREEN_NAME)); tabArgs.putString(EXTRA_SCREEN_NAME, args.getString(EXTRA_SCREEN_NAME));
} }
mPagerAdapter.addTab(UserTimelineFragment.class, tabArgs, getString(R.string.statuses), null, 0); mPagerAdapter.addTab(UserTimelineFragment.class, tabArgs, getString(R.string.statuses), R.drawable.ic_action_quote, 0);
if (Utils.isOfficialKeyAccount(context, accountId)) { if (Utils.isOfficialKeyAccount(context, accountId)) {
mPagerAdapter.addTab(UserMediaTimelineFragment.class, tabArgs, getString(R.string.media), null, 1); mPagerAdapter.addTab(UserMediaTimelineFragment.class, tabArgs, getString(R.string.media), R.drawable.ic_action_gallery, 1);
} }
mPagerAdapter.addTab(UserFavoritesFragment.class, tabArgs, getString(R.string.favorites), null, 2); mPagerAdapter.addTab(UserFavoritesFragment.class, tabArgs, getString(R.string.favorites), R.drawable.ic_action_star, 2);
mPagerIndicator.notifyDataSetChanged();
} }
private boolean shouldUseNativeMenu() { private boolean shouldUseNativeMenu() {

View File

@ -55,8 +55,6 @@ import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.astuetz.PagerSlidingTabStrip;
import org.mariotaku.twidere.R; import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.support.UserListSelectorActivity; import org.mariotaku.twidere.activity.support.UserListSelectorActivity;
import org.mariotaku.twidere.adapter.support.SupportTabsAdapter; import org.mariotaku.twidere.adapter.support.SupportTabsAdapter;
@ -74,6 +72,7 @@ import org.mariotaku.twidere.util.TwidereLinkify;
import org.mariotaku.twidere.view.ColorLabelRelativeLayout; import org.mariotaku.twidere.view.ColorLabelRelativeLayout;
import org.mariotaku.twidere.view.HeaderDrawerLayout; import org.mariotaku.twidere.view.HeaderDrawerLayout;
import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback; import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback;
import org.mariotaku.twidere.view.TabPagerIndicator;
import twitter4j.Twitter; import twitter4j.Twitter;
import twitter4j.TwitterException; import twitter4j.TwitterException;
@ -102,7 +101,7 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList
private Button mRetryButton; private Button mRetryButton;
private HeaderDrawerLayout mHeaderDrawerLayout; private HeaderDrawerLayout mHeaderDrawerLayout;
private ViewPager mViewPager; private ViewPager mViewPager;
private PagerSlidingTabStrip mPagerIndicator; private TabPagerIndicator mPagerIndicator;
private CardView mCardView; private CardView mCardView;
private SupportTabsAdapter mPagerAdapter; private SupportTabsAdapter mPagerAdapter;
@ -484,7 +483,7 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList
mRetryButton = (Button) mErrorRetryContainer.findViewById(R.id.retry); mRetryButton = (Button) mErrorRetryContainer.findViewById(R.id.retry);
mErrorMessageView = (TextView) mErrorRetryContainer.findViewById(R.id.error_message); mErrorMessageView = (TextView) mErrorRetryContainer.findViewById(R.id.error_message);
mViewPager = (ViewPager) contentView.findViewById(R.id.view_pager); mViewPager = (ViewPager) contentView.findViewById(R.id.view_pager);
mPagerIndicator = (PagerSlidingTabStrip) contentView.findViewById(R.id.view_pager_tabs); mPagerIndicator = (TabPagerIndicator) contentView.findViewById(R.id.view_pager_tabs);
} }
@Override @Override

View File

@ -28,13 +28,12 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.astuetz.PagerSlidingTabStrip;
import org.mariotaku.twidere.R; import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.support.SupportTabsAdapter; import org.mariotaku.twidere.adapter.support.SupportTabsAdapter;
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback; import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback;
import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface; import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface;
import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback; import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback;
import org.mariotaku.twidere.view.TabPagerIndicator;
public class UserListsFragment extends BaseSupportFragment implements RefreshScrollTopInterface, public class UserListsFragment extends BaseSupportFragment implements RefreshScrollTopInterface,
SupportFragmentCallback, SystemWindowsInsetsCallback { SupportFragmentCallback, SystemWindowsInsetsCallback {
@ -42,7 +41,7 @@ public class UserListsFragment extends BaseSupportFragment implements RefreshScr
private ViewPager mViewPager; private ViewPager mViewPager;
private SupportTabsAdapter mAdapter; private SupportTabsAdapter mAdapter;
private PagerSlidingTabStrip mPagerIndicator; private TabPagerIndicator mPagerIndicator;
private Fragment mCurrentVisibleFragment; private Fragment mCurrentVisibleFragment;
@ -90,7 +89,7 @@ public class UserListsFragment extends BaseSupportFragment implements RefreshScr
public void onViewCreated(final View view, final Bundle savedInstanceState) { public void onViewCreated(final View view, final Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
mViewPager = (ViewPager) view.findViewById(R.id.view_pager); mViewPager = (ViewPager) view.findViewById(R.id.view_pager);
mPagerIndicator = (PagerSlidingTabStrip) view.findViewById(R.id.view_pager_tabs); mPagerIndicator = (TabPagerIndicator) view.findViewById(R.id.view_pager_tabs);
} }
@Override @Override

View File

@ -19,60 +19,61 @@
package org.mariotaku.twidere.model; package org.mariotaku.twidere.model;
import static org.mariotaku.twidere.util.CompareUtils.bundleEquals;
import static org.mariotaku.twidere.util.CompareUtils.classEquals;
import static org.mariotaku.twidere.util.CompareUtils.objectEquals;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import org.mariotaku.twidere.TwidereConstants; import org.mariotaku.twidere.TwidereConstants;
import static org.mariotaku.twidere.util.CompareUtils.bundleEquals;
import static org.mariotaku.twidere.util.CompareUtils.classEquals;
import static org.mariotaku.twidere.util.CompareUtils.objectEquals;
public class SupportTabSpec implements Comparable<SupportTabSpec>, TwidereConstants { public class SupportTabSpec implements Comparable<SupportTabSpec>, TwidereConstants {
public final String name; public final String name;
public final Object icon; public final Object icon;
public final String type; public final String type;
public final Class<? extends Fragment> cls; public final Class<? extends Fragment> cls;
public final Bundle args; public final Bundle args;
public final int position; public final int position;
public SupportTabSpec(final String name, final Object icon, final Class<? extends Fragment> cls, final Bundle args, public SupportTabSpec(final String name, final Object icon, final Class<? extends Fragment> cls, final Bundle args,
final int position) { final int position) {
this(name, icon, null, cls, args, position); this(name, icon, null, cls, args, position);
} }
public SupportTabSpec(final String name, final Object icon, final String type, final Class<? extends Fragment> cls, public SupportTabSpec(final String name, final Object icon, final String type, final Class<? extends Fragment> cls,
final Bundle args, final int position) { final Bundle args, final int position) {
if (cls == null) throw new IllegalArgumentException("Fragment cannot be null!"); if (cls == null) throw new IllegalArgumentException("Fragment cannot be null!");
if (name == null && icon == null) if (name == null && icon == null)
throw new IllegalArgumentException("You must specify a name or icon for this tab!"); throw new IllegalArgumentException("You must specify a name or icon for this tab!");
this.name = name; this.name = name;
this.icon = icon; this.icon = icon;
this.type = type; this.type = type;
this.cls = cls; this.cls = cls;
this.args = args; this.args = args;
this.position = position; this.position = position;
} }
@Override @Override
public int compareTo(final SupportTabSpec another) { public int compareTo(@NonNull final SupportTabSpec another) {
return position - another.position; return position - another.position;
} }
@Override @Override
public boolean equals(final Object o) { public boolean equals(final Object o) {
if (!(o instanceof SupportTabSpec)) return false; if (!(o instanceof SupportTabSpec)) return false;
final SupportTabSpec spec = (SupportTabSpec) o; final SupportTabSpec spec = (SupportTabSpec) o;
return objectEquals(name, spec.name) && objectEquals(icon, spec.icon) && classEquals(cls, spec.cls) return objectEquals(name, spec.name) && objectEquals(icon, spec.icon) && classEquals(cls, spec.cls)
&& bundleEquals(args, spec.args) && position == spec.position; && bundleEquals(args, spec.args) && position == spec.position;
} }
@Override @Override
public String toString() { public String toString() {
return "SupportTabSpec{name=" + name + ", icon=" + icon + ", type=" + type + ", cls=" + cls + ", args=" + args return "SupportTabSpec{name=" + name + ", icon=" + icon + ", type=" + type + ", cls=" + cls + ", args=" + args
+ ", position=" + position + "}"; + ", position=" + position + "}";
} }
} }

View File

@ -19,11 +19,6 @@
package org.mariotaku.twidere.preference; package org.mariotaku.twidere.preference;
import static org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText;
import static org.mariotaku.twidere.util.Utils.getDefaultTextSize;
import static org.mariotaku.twidere.util.Utils.getLinkHighlightOptionInt;
import static org.mariotaku.twidere.util.Utils.getSampleDisplayName;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
@ -38,106 +33,108 @@ import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R; import org.mariotaku.twidere.R;
import org.mariotaku.twidere.util.ThemeUtils; import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.TwidereLinkify; import org.mariotaku.twidere.util.TwidereLinkify;
import org.mariotaku.twidere.view.CardItemLinearLayout;
import org.mariotaku.twidere.view.ForegroundImageView; import org.mariotaku.twidere.view.ForegroundImageView;
import org.mariotaku.twidere.view.holder.StatusListViewHolder; import org.mariotaku.twidere.view.holder.StatusListViewHolder;
import static org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText;
import static org.mariotaku.twidere.util.Utils.getDefaultTextSize;
import static org.mariotaku.twidere.util.Utils.getLinkHighlightOptionInt;
import static org.mariotaku.twidere.util.Utils.getSampleDisplayName;
public class CardPreviewPreference extends Preference implements Constants, OnSharedPreferenceChangeListener { public class CardPreviewPreference extends Preference implements Constants, OnSharedPreferenceChangeListener {
private final LayoutInflater mInflater; private final LayoutInflater mInflater;
private final SharedPreferences mPreferences; private final SharedPreferences mPreferences;
private final TwidereLinkify mLinkify; private final TwidereLinkify mLinkify;
private StatusListViewHolder mHolder; private StatusListViewHolder mHolder;
private boolean mCompactModeChanged; private boolean mCompactModeChanged;
public CardPreviewPreference(final Context context) { public CardPreviewPreference(final Context context) {
this(context, null); this(context, null);
} }
public CardPreviewPreference(final Context context, final AttributeSet attrs) { public CardPreviewPreference(final Context context, final AttributeSet attrs) {
this(context, attrs, 0); this(context, attrs, 0);
} }
public CardPreviewPreference(final Context context, final AttributeSet attrs, final int defStyle) { public CardPreviewPreference(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
mInflater = LayoutInflater.from(context); mInflater = LayoutInflater.from(context);
mLinkify = new TwidereLinkify(null); mLinkify = new TwidereLinkify(null);
mLinkify.setLinkTextColor(ThemeUtils.getUserLinkTextColor(context)); mLinkify.setLinkTextColor(ThemeUtils.getUserLinkTextColor(context));
mPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); mPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
mPreferences.registerOnSharedPreferenceChangeListener(this); mPreferences.registerOnSharedPreferenceChangeListener(this);
} }
@Override @Override
public View getView(final View convertView, final ViewGroup parent) { public View getView(final View convertView, final ViewGroup parent) {
if (mCompactModeChanged) return super.getView(null, parent); if (mCompactModeChanged) return super.getView(null, parent);
return super.getView(convertView, parent); return super.getView(convertView, parent);
} }
@Override @Override
public void onSharedPreferenceChanged(final SharedPreferences preferences, final String key) { public void onSharedPreferenceChanged(final SharedPreferences preferences, final String key) {
if (mHolder == null) return; if (mHolder == null) return;
if (KEY_COMPACT_CARDS.equals(key)) { if (KEY_COMPACT_CARDS.equals(key)) {
mCompactModeChanged = true; mCompactModeChanged = true;
} }
notifyChanged(); notifyChanged();
} }
@Override @Override
protected void onBindView(final View view) { protected void onBindView(final View view) {
if (mPreferences == null) return; if (mPreferences == null) return;
mCompactModeChanged = false; mCompactModeChanged = false;
final Context context = getContext(); final Context context = getContext();
final int highlightOption = getLinkHighlightOptionInt(context); final int highlightOption = getLinkHighlightOptionInt(context);
final boolean nameFirst = mPreferences.getBoolean(KEY_NAME_FIRST, true); final boolean nameFirst = mPreferences.getBoolean(KEY_NAME_FIRST, true);
final boolean display_image_preview = mPreferences.getBoolean(KEY_DISPLAY_IMAGE_PREVIEW, false); final boolean display_image_preview = mPreferences.getBoolean(KEY_DISPLAY_IMAGE_PREVIEW, false);
final boolean display_profile_image = mPreferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true); final boolean display_profile_image = mPreferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true);
final boolean nickname_only = mPreferences.getBoolean(KEY_NICKNAME_ONLY, false); final boolean nickname_only = mPreferences.getBoolean(KEY_NICKNAME_ONLY, false);
mHolder = new StatusListViewHolder(view); mHolder = new StatusListViewHolder(view);
mLinkify.setHighlightOption(highlightOption); mLinkify.setHighlightOption(highlightOption);
mHolder.setDisplayNameFirst(nameFirst); mHolder.setDisplayNameFirst(nameFirst);
mHolder.setNicknameOnly(nickname_only); mHolder.setNicknameOnly(nickname_only);
mHolder.setShowAsGap(false); mHolder.setShowAsGap(false);
mHolder.setIsMyStatus(false); mHolder.setIsMyStatus(false);
mHolder.setTextSize(mPreferences.getInt(KEY_TEXT_SIZE, getDefaultTextSize(context))); mHolder.setTextSize(mPreferences.getInt(KEY_TEXT_SIZE, getDefaultTextSize(context)));
mHolder.image_preview_container.setVisibility(display_image_preview ? View.VISIBLE : View.GONE); mHolder.image_preview_container.setVisibility(display_image_preview ? View.VISIBLE : View.GONE);
mHolder.profile_image.setVisibility(display_profile_image ? View.VISIBLE : View.GONE); mHolder.profile_image.setVisibility(display_profile_image ? View.VISIBLE : View.GONE);
mHolder.image_preview_progress.setVisibility(View.GONE); mHolder.image_preview_progress.setVisibility(View.GONE);
if (mHolder.profile_image instanceof ForegroundImageView) { if (mHolder.profile_image instanceof ForegroundImageView) {
((ForegroundImageView) mHolder.profile_image).setForeground(null); ((ForegroundImageView) mHolder.profile_image).setForeground(null);
} }
if (mHolder.image_preview instanceof ForegroundImageView) { if (mHolder.image_preview instanceof ForegroundImageView) {
((ForegroundImageView) mHolder.image_preview).setForeground(null); ((ForegroundImageView) mHolder.image_preview).setForeground(null);
} }
if (mHolder.content instanceof CardItemLinearLayout) { mHolder.content.setItemSelector(null);
((CardItemLinearLayout) mHolder.content).setItemSelector(null); mHolder.profile_image.setImageResource(R.drawable.ic_launcher);
} mHolder.image_preview.setImageResource(R.drawable.twidere_feature_graphic);
mHolder.profile_image.setImageResource(R.drawable.ic_launcher); mHolder.name.setText(nickname_only ? TWIDERE_PREVIEW_NICKNAME : context.getString(R.string.name_with_nickname,
mHolder.image_preview.setImageResource(R.drawable.twidere_feature_graphic); TWIDERE_PREVIEW_NAME, TWIDERE_PREVIEW_NICKNAME));
mHolder.name.setText(nickname_only ? TWIDERE_PREVIEW_NICKNAME : context.getString(R.string.name_with_nickname, mHolder.screen_name.setText("@" + TWIDERE_PREVIEW_SCREEN_NAME);
TWIDERE_PREVIEW_NAME, TWIDERE_PREVIEW_NICKNAME)); if (highlightOption != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) {
mHolder.screen_name.setText("@" + TWIDERE_PREVIEW_SCREEN_NAME); mHolder.text.setText(Html.fromHtml(TWIDERE_PREVIEW_TEXT_HTML));
if (highlightOption != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) { mLinkify.applyAllLinks(mHolder.text, 0, false);
mHolder.text.setText(Html.fromHtml(TWIDERE_PREVIEW_TEXT_HTML)); mLinkify.applyUserProfileLinkNoHighlight(mHolder.name, 0, 0, TWIDERE_PREVIEW_SCREEN_NAME);
mLinkify.applyAllLinks(mHolder.text, 0, false); mLinkify.applyUserProfileLinkNoHighlight(mHolder.screen_name, 0, 0, TWIDERE_PREVIEW_SCREEN_NAME);
mLinkify.applyUserProfileLinkNoHighlight(mHolder.name, 0, 0, TWIDERE_PREVIEW_SCREEN_NAME); } else {
mLinkify.applyUserProfileLinkNoHighlight(mHolder.screen_name, 0, 0, TWIDERE_PREVIEW_SCREEN_NAME); mHolder.text.setText(toPlainText(TWIDERE_PREVIEW_TEXT_HTML));
} else { }
mHolder.text.setText(toPlainText(TWIDERE_PREVIEW_TEXT_HTML)); final String display_name = getSampleDisplayName(context, nameFirst, nickname_only);
} mHolder.reply_retweet_status.setText(context.getString(R.string.retweeted_by_name, display_name));
final String display_name = getSampleDisplayName(context, nameFirst, nickname_only); mHolder.reply_retweet_status.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_indicator_retweet, 0, 0, 0);
mHolder.reply_retweet_status.setText(context.getString(R.string.retweeted_by_name, display_name)); mHolder.time.setTime(System.currentTimeMillis() - 360000);
mHolder.reply_retweet_status.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_indicator_retweet, 0, 0, 0); mHolder.time.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_indicator_media, 0);
mHolder.time.setTime(System.currentTimeMillis() - 360000); super.onBindView(view);
mHolder.time.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_indicator_media, 0); }
super.onBindView(view);
}
@Override @Override
protected View onCreateView(final ViewGroup parent) { protected View onCreateView(final ViewGroup parent) {
if (mPreferences != null && mPreferences.getBoolean(KEY_COMPACT_CARDS, false)) if (mPreferences != null && mPreferences.getBoolean(KEY_COMPACT_CARDS, false))
return mInflater.inflate(R.layout.list_item_status_compact_deprecated, parent, false); return mInflater.inflate(R.layout.list_item_status_compact_deprecated, parent, false);
return mInflater.inflate(R.layout.list_item_status_deprecated, parent, false); return mInflater.inflate(R.layout.list_item_status_deprecated, parent, false);
} }
} }

View File

@ -0,0 +1,41 @@
/*
* 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.service;
import android.annotation.TargetApi;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.os.Build;
/**
* Created by mariotaku on 14/12/12.
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class BackgroundJobService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
return false;
}
}

View File

@ -59,11 +59,13 @@ import org.mariotaku.twidere.service.BackgroundOperationService;
import org.mariotaku.twidere.task.CacheUsersStatusesTask; import org.mariotaku.twidere.task.CacheUsersStatusesTask;
import org.mariotaku.twidere.task.ManagedAsyncTask; import org.mariotaku.twidere.task.ManagedAsyncTask;
import org.mariotaku.twidere.task.TwidereAsyncTask; import org.mariotaku.twidere.task.TwidereAsyncTask;
import org.mariotaku.twidere.util.collection.LongSparseMap;
import org.mariotaku.twidere.util.message.FavoriteCreatedEvent; import org.mariotaku.twidere.util.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.util.message.FavoriteDestroyedEvent; import org.mariotaku.twidere.util.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.util.message.FriendshipUpdatedEvent; import org.mariotaku.twidere.util.message.FriendshipUpdatedEvent;
import org.mariotaku.twidere.util.message.ProfileUpdatedEvent; import org.mariotaku.twidere.util.message.ProfileUpdatedEvent;
import org.mariotaku.twidere.util.message.StatusDestroyedEvent; import org.mariotaku.twidere.util.message.StatusDestroyedEvent;
import org.mariotaku.twidere.util.message.StatusListChangedEvent;
import org.mariotaku.twidere.util.message.StatusRetweetedEvent; import org.mariotaku.twidere.util.message.StatusRetweetedEvent;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -116,6 +118,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
private int mGetReceivedDirectMessagesTaskId, mGetSentDirectMessagesTaskId; private int mGetReceivedDirectMessagesTaskId, mGetSentDirectMessagesTaskId;
private int mGetLocalTrendsTaskId; private int mGetLocalTrendsTaskId;
private LongSparseMap<Long> mCreatingFavoriteIds = new LongSparseMap<>();
private LongSparseMap<Long> mDestroyingFavoriteIds = new LongSparseMap<>();
public AsyncTwitterWrapper(final Context context) { public AsyncTwitterWrapper(final Context context) {
mContext = context; mContext = context;
final TwidereApplication app = TwidereApplication.getInstance(context); final TwidereApplication app = TwidereApplication.getInstance(context);
@ -135,6 +140,15 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
return mAsyncTaskManager.add(task, true); return mAsyncTaskManager.add(task, true);
} }
public boolean isCreatingFavorite(final long accountId, final long statusId) {
return mCreatingFavoriteIds.has(accountId, statusId);
}
public boolean isDestroyingFavorite(final long accountId, final long statusId) {
return mDestroyingFavoriteIds.has(accountId, statusId);
}
public void clearNotificationAsync(final int notificationType) { public void clearNotificationAsync(final int notificationType) {
clearNotificationAsync(notificationType, 0); clearNotificationAsync(notificationType, 0);
} }
@ -849,8 +863,17 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
} }
} }
@Override
protected void onPreExecute() {
super.onPreExecute();
mCreatingFavoriteIds.put(account_id, status_id);
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
bus.post(new StatusListChangedEvent());
}
@Override @Override
protected void onPostExecute(final SingleResponse<ParcelableStatus> result) { protected void onPostExecute(final SingleResponse<ParcelableStatus> result) {
mCreatingFavoriteIds.remove(account_id, status_id);
if (result.hasData()) { if (result.hasData()) {
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus(); final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
bus.post(new FavoriteCreatedEvent(result.getData())); bus.post(new FavoriteCreatedEvent(result.getData()));
@ -1367,8 +1390,17 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
return SingleResponse.getInstance(); return SingleResponse.getInstance();
} }
@Override
protected void onPreExecute() {
super.onPreExecute();
mDestroyingFavoriteIds.put(account_id, status_id);
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
bus.post(new StatusListChangedEvent());
}
@Override @Override
protected void onPostExecute(final SingleResponse<ParcelableStatus> result) { protected void onPostExecute(final SingleResponse<ParcelableStatus> result) {
mDestroyingFavoriteIds.remove(account_id, status_id);
if (result.hasData()) { if (result.hasData()) {
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus(); final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
bus.post(new FavoriteDestroyedEvent(result.getData())); bus.post(new FavoriteDestroyedEvent(result.getData()));

View File

@ -0,0 +1,66 @@
/*
* 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.collection;
import android.support.v4.util.LongSparseArray;
import java.util.HashSet;
/**
* Created by mariotaku on 14/12/12.
*/
public class LongSparseMap<T> {
private final LongSparseArray<HashSet<T>> internalArray;
public LongSparseMap() {
internalArray = new LongSparseArray<>();
}
public boolean put(long key, T value) {
final int idx = internalArray.indexOfKey(key);
final HashSet<T> set;
if (idx < 0) {
set = new HashSet<>();
internalArray.put(key, set);
} else {
set = internalArray.valueAt(idx);
}
return set.add(value);
}
public boolean clear(long key) {
final int idx = internalArray.indexOfKey(key);
if (idx < 0) return false;
internalArray.valueAt(idx).clear();
return true;
}
public boolean remove(long key, T value) {
final int idx = internalArray.indexOfKey(key);
return idx >= 0 && internalArray.valueAt(idx).remove(value);
}
public boolean has(long key, T value) {
final int idx = internalArray.indexOfKey(key);
return idx >= 0 && internalArray.valueAt(idx).contains(value);
}
}

View File

@ -0,0 +1,26 @@
/*
* 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.message;
/**
* Created by mariotaku on 14/12/12.
*/
public class StatusListChangedEvent {
}

View File

@ -1,7 +1,12 @@
package org.mariotaku.twidere.view; package org.mariotaku.twidere.view;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.support.annotation.IntDef;
import android.support.v4.view.PagerAdapter; import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager;
@ -14,39 +19,56 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import org.mariotaku.twidere.R; import org.mariotaku.twidere.R;
import org.mariotaku.twidere.view.iface.PagerIndicator; import org.mariotaku.twidere.view.iface.PagerIndicator;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/** /**
* Created by mariotaku on 14/10/21. * Created by mariotaku on 14/10/21.
*/ */
public class TabPagerIndicator extends RecyclerView implements PagerIndicator { public class TabPagerIndicator extends RecyclerView implements PagerIndicator {
public static final int ICON = 0x1;
public static final int LABEL = 0x2;
public static final int BOTH = ICON | LABEL;
private final int mStripHeight; private final int mStripHeight;
private ViewPager mViewPager;
private final TabPagerIndicatorAdapter mIndicatorAdapter; private final TabPagerIndicatorAdapter mIndicatorAdapter;
private ViewPager mViewPager;
private PagerAdapter mPagerProvider; private PagerAdapter mPagerProvider;
private OnPageChangeListener mPageChangeListener; private OnPageChangeListener mPageChangeListener;
private int mOption;
private boolean mTabExpandEnabled;
private int mHorizontalPadding, mVerticalPadding;
public TabPagerIndicator(Context context, AttributeSet attrs, int defStyle) { public TabPagerIndicator(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
final Resources res = getResources();
mIndicatorAdapter = new TabPagerIndicatorAdapter(this);
mStripHeight = getResources().getDimensionPixelSize(R.dimen.element_spacing_small);
ViewCompat.setOverScrollMode(this, ViewCompat.OVER_SCROLL_NEVER); ViewCompat.setOverScrollMode(this, ViewCompat.OVER_SCROLL_NEVER);
setHorizontalScrollBarEnabled(false); setHorizontalScrollBarEnabled(false);
setVerticalScrollBarEnabled(false); setVerticalScrollBarEnabled(false);
setLayoutManager(new TabLayoutManager(this)); setLayoutManager(new TabLayoutManager(this));
mIndicatorAdapter = new TabPagerIndicatorAdapter(this); setItemContext(context);
setAdapter(mIndicatorAdapter); setAdapter(mIndicatorAdapter);
mStripHeight = getResources().getDimensionPixelSize(R.dimen.element_spacing_small); setTabDisplayOption(ICON);
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabPagerIndicator);
setTabExpandEnabled(a.getBoolean(R.styleable.TabPagerIndicator_tabExpandEnabled, false));
setHorizontalPadding(a.getDimensionPixelSize(R.styleable.TabPagerIndicator_tabHorizontalPadding, 0));
setVerticalPadding(a.getDimensionPixelSize(R.styleable.TabPagerIndicator_tabHorizontalPadding, 0));
setStripColor(a.getColor(R.styleable.TabPagerIndicator_tabStripColor, 0));
setIconColor(a.getColor(R.styleable.TabPagerIndicator_tabIconColor, 0));
setTabDisplayOption(a.getInt(R.styleable.TabPagerIndicator_tabDisplayOption, ICON));
a.recycle();
} }
public void setStripColor(int color) {
mIndicatorAdapter.setStripColor(color);
}
public TabPagerIndicator(Context context, AttributeSet attrs) { public TabPagerIndicator(Context context, AttributeSet attrs) {
this(context, attrs, 0); this(context, attrs, 0);
@ -56,11 +78,91 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator {
this(context, null); this(context, null);
} }
public int getCount() {
return mIndicatorAdapter.getItemCount();
}
public Context getItemContext() {
return mIndicatorAdapter.getItemContext();
}
public void setItemContext(Context context) {
mIndicatorAdapter.setItemContext(context);
}
public int getStripHeight() {
return mStripHeight;
}
@Override @Override
public void notifyDataSetChanged() { public void notifyDataSetChanged() {
mIndicatorAdapter.notifyDataSetChanged(); mIndicatorAdapter.notifyDataSetChanged();
} }
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (mPageChangeListener == null) return;
mPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
@Override
public void onPageSelected(int position) {
mIndicatorAdapter.notifyDataSetChanged();
if (mPageChangeListener == null) return;
mPageChangeListener.onPageSelected(position);
}
@Override
public void onPageScrollStateChanged(int state) {
if (mPageChangeListener == null) return;
mPageChangeListener.onPageScrollStateChanged(state);
}
public void setBadge(int position, int count) {
mIndicatorAdapter.setBadge(position, count);
}
public void setDisplayBadge(boolean display) {
mIndicatorAdapter.setDisplayBadge(display);
}
public void setIconColor(int color) {
mIndicatorAdapter.setIconColor(color);
}
public void setStripColor(int color) {
mIndicatorAdapter.setStripColor(color);
}
@DisplayOption
public void setTabDisplayOption(int flags) {
mOption = flags;
notifyDataSetChanged();
}
private void dispatchTabClick(int position) {
final int currentItem = getCurrentItem();
setCurrentItem(position);
if (mPagerProvider instanceof TabListener) {
if (currentItem != position) {
((TabListener) mPagerProvider).onPageSelected(position);
} else {
((TabListener) mPagerProvider).onPageReselected(position);
}
}
}
private boolean dispatchTabLongClick(int position) {
if (mPagerProvider instanceof TabListener) {
return ((TabListener) mPagerProvider).onTabLongClick(position);
}
return false;
}
private int getCurrentItem() {
return mViewPager.getCurrentItem();
}
@Override @Override
public void setCurrentItem(int item) { public void setCurrentItem(int item) {
mViewPager.setCurrentItem(item); mViewPager.setCurrentItem(item);
@ -88,62 +190,46 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator {
mIndicatorAdapter.setTabProvider((TabProvider) adapter); mIndicatorAdapter.setTabProvider((TabProvider) adapter);
} }
@Override private int getTabHorizontalPadding() {
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { return mHorizontalPadding;
if (mPageChangeListener == null) return;
mPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
} }
@Override private int getTabVerticalPadding() {
public void onPageSelected(int position) { return mVerticalPadding;
mIndicatorAdapter.notifyDataSetChanged();
if (mPageChangeListener == null) return;
mPageChangeListener.onPageSelected(position);
} }
@Override private boolean isIconDisplayed() {
public void onPageScrollStateChanged(int state) { return (mOption & ICON) != 0;
if (mPageChangeListener == null) return;
mPageChangeListener.onPageScrollStateChanged(state);
} }
public int getCount() { private boolean isLabelDisplayed() {
return mIndicatorAdapter.getItemCount(); return (mOption & LABEL) != 0;
} }
public void setBadge(int position, int count) { private boolean isTabExpandEnabled() {
mIndicatorAdapter.setBadge(position, count); return mTabExpandEnabled;
} }
public void setDisplayLabel(boolean display) { public void setTabExpandEnabled(boolean expandEnabled) {
mTabExpandEnabled = expandEnabled;
} }
public void setDisplayIcon(boolean display) { private void setHorizontalPadding(int padding) {
mHorizontalPadding = padding;
notifyDataSetChanged();
} }
public int getStripHeight() { private void setVerticalPadding(int padding) {
return mStripHeight; mVerticalPadding = padding;
notifyDataSetChanged();
} }
public void setIconColor(int color) { @IntDef({ICON, LABEL, BOTH})
mIndicatorAdapter.setIconColor(color); @Retention(RetentionPolicy.SOURCE)
public @interface DisplayOption {
} }
public Context getItemContext() { private static class TabPagerIndicatorAdapter extends Adapter<TabItemHolder> {
return mIndicatorAdapter.getItemContext();
}
public void setItemContext(Context context) {
mIndicatorAdapter.setItemContext(context);
}
public void setDisplayBadge(boolean display) {
mIndicatorAdapter.setDisplayBadge(display);
}
private static class TabPagerIndicatorAdapter extends Adapter<TabItemHolder> implements OnClickListener, OnLongClickListener {
private final TabPagerIndicator mIndicator; private final TabPagerIndicator mIndicator;
private final SparseIntArray mUnreadCounts; private final SparseIntArray mUnreadCounts;
@ -159,61 +245,8 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator {
mUnreadCounts = new SparseIntArray(); mUnreadCounts = new SparseIntArray();
} }
@Override public Context getItemContext() {
public TabItemHolder onCreateViewHolder(ViewGroup parent, int viewType) { return mItemContext;
final View view = mInflater.inflate(R.layout.tab_item_home, parent, false);
view.setOnClickListener(this);
view.setOnLongClickListener(this);
final View selectedIndicator = view.findViewById(R.id.selected_indicator);
final ViewGroup.LayoutParams lp = selectedIndicator.getLayoutParams();
lp.height = mIndicator.getStripHeight();
selectedIndicator.setLayoutParams(lp);
return new TabItemHolder(view);
}
@Override
public void onBindViewHolder(TabItemHolder holder, int position) {
final Drawable icon = mTabProvider.getPageIcon(position);
final CharSequence title = mTabProvider.getPageTitle(position);
holder.setTabData(position, icon, title, mIndicator.getCurrentItem() == position);
holder.setStripColor(mStripColor);
holder.setIconColor(mIconColor);
holder.setBadge(mUnreadCounts.get(position, 0), mDisplayBadge);
}
@Override
public int getItemCount() {
if (mTabProvider == null) return 0;
return mTabProvider.getCount();
}
public void setTabProvider(TabProvider tabProvider) {
mTabProvider = tabProvider;
notifyDataSetChanged();
}
@Override
public void onClick(View v) {
final Object tag = v.getTag();
if (!(tag instanceof Integer)) return;
mIndicator.dispatchTabClick((Integer) tag);
}
@Override
public boolean onLongClick(View v) {
final Object tag = v.getTag();
if (!(tag instanceof Integer)) return false;
return mIndicator.dispatchTabLongClick((Integer) tag);
}
public void setStripColor(int color) {
mStripColor = color;
notifyDataSetChanged();
}
public void setIconColor(int color) {
mIconColor = color;
notifyDataSetChanged();
} }
public void setItemContext(Context itemContext) { public void setItemContext(Context itemContext) {
@ -221,8 +254,30 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator {
mInflater = LayoutInflater.from(itemContext); mInflater = LayoutInflater.from(itemContext);
} }
public Context getItemContext() { @Override
return mItemContext; public TabItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (mIndicator == null) throw new IllegalStateException("item context not set");
final View view = mInflater.inflate(R.layout.layout_tab_item, parent, false);
return new TabItemHolder(mIndicator, view);
}
@Override
public void onBindViewHolder(TabItemHolder holder, int position) {
final Drawable icon = mTabProvider.getPageIcon(position);
final CharSequence title = mTabProvider.getPageTitle(position);
holder.setTabData(icon, title, mIndicator.getCurrentItem() == position);
holder.setPadding(mIndicator.getTabHorizontalPadding(), mIndicator.getTabVerticalPadding());
holder.setStripHeight(mIndicator.getStripHeight());
holder.setStripColor(mStripColor);
holder.setIconColor(mIconColor);
holder.setBadge(mUnreadCounts.get(position, 0), mDisplayBadge);
holder.setDisplayOption(mIndicator.isIconDisplayed(), mIndicator.isLabelDisplayed());
}
@Override
public int getItemCount() {
if (mTabProvider == null) return 0;
return mTabProvider.getCount();
} }
public void setBadge(int position, int count) { public void setBadge(int position, int count) {
@ -234,67 +289,88 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator {
mDisplayBadge = display; mDisplayBadge = display;
notifyDataSetChanged(); notifyDataSetChanged();
} }
}
private void dispatchTabClick(int position) { public void setIconColor(int color) {
final int currentItem = getCurrentItem(); mIconColor = color;
setCurrentItem(position); notifyDataSetChanged();
if (mPagerProvider instanceof TabListener) {
if (currentItem != position) {
((TabListener) mPagerProvider).onPageSelected(position);
} else {
((TabListener) mPagerProvider).onPageReselected(position);
}
}
}
private boolean dispatchTabLongClick(int position) {
if (mPagerProvider instanceof TabListener) {
return ((TabListener) mPagerProvider).onTabLongClick(position);
}
return false;
}
private int getCurrentItem() {
return mViewPager.getCurrentItem();
}
private static class TabItemHolder extends ViewHolder {
private final View itemView;
private final ImageView iconView;
private final View selectedIndicator;
private final BadgeView badgeView;
public TabItemHolder(View itemView) {
super(itemView);
this.itemView = itemView;
selectedIndicator = itemView.findViewById(R.id.selected_indicator);
iconView = (ImageView) itemView.findViewById(R.id.tab_icon);
badgeView = (BadgeView) itemView.findViewById(R.id.unread_indicator);
}
public void setTabData(int position, Drawable icon, CharSequence title, boolean activated) {
itemView.setTag(position);
itemView.setContentDescription(title);
iconView.setImageDrawable(icon);
iconView.setContentDescription(title);
selectedIndicator.setVisibility(activated ? VISIBLE : INVISIBLE);
} }
public void setStripColor(int color) { public void setStripColor(int color) {
selectedIndicator.setBackgroundColor(color); mStripColor = color;
notifyDataSetChanged();
} }
public void setIconColor(int color) { public void setTabProvider(TabProvider tabProvider) {
iconView.setColorFilter(color); mTabProvider = tabProvider;
notifyDataSetChanged();
}
}
private static class TabItemHolder extends ViewHolder implements OnClickListener, OnLongClickListener {
private final TabPagerIndicator indicator;
private final ItemLayout itemView;
private final ImageView iconView;
private final TextView labelView;
private final BadgeView badgeView;
public TabItemHolder(TabPagerIndicator indicator, View itemView) {
super(itemView);
this.indicator = indicator;
this.itemView = (ItemLayout) itemView;
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
iconView = (ImageView) itemView.findViewById(R.id.tab_icon);
labelView = (TextView) itemView.findViewById(R.id.tab_label);
badgeView = (BadgeView) itemView.findViewById(R.id.unread_indicator);
}
@Override
public void onClick(View v) {
indicator.dispatchTabClick(getPosition());
}
@Override
public boolean onLongClick(View v) {
return indicator.dispatchTabLongClick(getPosition());
} }
public void setBadge(int count, boolean display) { public void setBadge(int count, boolean display) {
badgeView.setText(String.valueOf(count)); badgeView.setText(String.valueOf(count));
badgeView.setVisibility(display && count > 0 ? VISIBLE : GONE); badgeView.setVisibility(display && count > 0 ? VISIBLE : GONE);
} }
public void setDisplayOption(boolean iconDisplayed, boolean labelDisplayed) {
iconView.setVisibility(iconDisplayed ? VISIBLE : GONE);
labelView.setVisibility(labelDisplayed ? VISIBLE : GONE);
}
public void setIconColor(int color) {
if (color != 0) {
iconView.setColorFilter(color);
} else {
iconView.clearColorFilter();
}
}
public void setPadding(int horizontalPadding, int verticalPadding) {
itemView.setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding);
}
public void setStripColor(int color) {
itemView.setStripColor(color);
}
public void setStripHeight(int stripHeight) {
itemView.setStripHeight(stripHeight);
}
public void setTabData(Drawable icon, CharSequence title, boolean activated) {
itemView.setContentDescription(title);
iconView.setImageDrawable(icon);
labelView.setText(title);
itemView.setIsCurrent(activated);
}
} }
public static class TabLayoutManager extends LinearLayoutManager { public static class TabLayoutManager extends LinearLayoutManager {
@ -308,13 +384,59 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator {
@Override @Override
public void measureChildWithMargins(View child, int widthUsed, int heightUsed) { public void measureChildWithMargins(View child, int widthUsed, int heightUsed) {
// first get default measured size
super.measureChildWithMargins(child, widthUsed, heightUsed);
if (!mIndicator.isTabExpandEnabled()) return;
final int count = mIndicator.getCount(); final int count = mIndicator.getCount();
if (count == 0) return; if (count == 0) return;
final int parentHeight = mIndicator.getHeight(), parentWidth = mIndicator.getWidth(); final int parentHeight = mIndicator.getHeight(), parentWidth = mIndicator.getWidth();
final int width = Math.max(parentWidth / count, parentHeight); final int width = Math.max(parentWidth / count, child.getMeasuredWidth());
final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(parentHeight, MeasureSpec.EXACTLY); final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(parentHeight, MeasureSpec.EXACTLY);
final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY); final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
child.measure(widthMeasureSpec, heightMeasureSpec); child.measure(widthMeasureSpec, heightMeasureSpec);
} }
} }
public static final class ItemLayout extends RelativeLayout {
private final Paint mStripPaint;
private boolean mIsCurrent;
private int mStripColor;
private int mStripHeight;
public ItemLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mStripPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
setWillNotDraw(false);
}
public void setIsCurrent(boolean isCurrent) {
if (mIsCurrent == isCurrent) return;
mIsCurrent = isCurrent;
invalidate();
}
public void setStripColor(int stripColor) {
if (mStripColor == stripColor) return;
mStripColor = stripColor;
mStripPaint.setColor(stripColor);
invalidate();
}
public void setStripHeight(int stripHeight) {
if (mStripHeight == stripHeight) return;
mStripHeight = stripHeight;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
if (mIsCurrent) {
final int width = canvas.getWidth(), height = canvas.getHeight();
canvas.drawRect(0, height - mStripHeight, width, height, mStripPaint);
}
super.onDraw(canvas);
}
}
} }

View File

@ -14,6 +14,7 @@ import org.mariotaku.twidere.adapter.iface.IStatusesAdapter;
import org.mariotaku.twidere.model.ParcelableMedia; import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.model.ParcelableStatus; import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatus.CursorIndices; import org.mariotaku.twidere.model.ParcelableStatus.CursorIndices;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.ImageLoaderWrapper; import org.mariotaku.twidere.util.ImageLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler; import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.UserColorNicknameUtils; import org.mariotaku.twidere.util.UserColorNicknameUtils;
@ -84,11 +85,12 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements OnClick
public void displayStatus(final ParcelableStatus status) { public void displayStatus(final ParcelableStatus status) {
displayStatus(adapter.getContext(), adapter.getImageLoader(), displayStatus(adapter.getContext(), adapter.getImageLoader(),
adapter.getImageLoadingHandler(), status); adapter.getImageLoadingHandler(), adapter.getTwitterWrapper(), status);
} }
public void displayStatus(final Context context, final ImageLoaderWrapper loader, public void displayStatus(final Context context, final ImageLoaderWrapper loader,
final ImageLoadingHandler handler, final ParcelableStatus status) { final ImageLoadingHandler handler, final AsyncTwitterWrapper twitter,
final ParcelableStatus status) {
final ParcelableMedia[] media = status.media; final ParcelableMedia[] media = status.media;
if (status.retweet_id > 0) { if (status.retweet_id > 0) {
@ -163,12 +165,18 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements OnClick
retweetCountView.setEnabled(!status.user_is_protected); retweetCountView.setEnabled(!status.user_is_protected);
retweetCountView.setActivated(Utils.isMyRetweet(status)); retweetCountView.setActivated(Utils.isMyRetweet(status));
favoriteCountView.setActivated(status.is_favorite); if (twitter.isDestroyingFavorite(status.account_id, status.id)) {
favoriteCountView.setActivated(false);
} else {
favoriteCountView.setActivated(twitter.isCreatingFavorite(status.account_id, status.id)
|| status.is_favorite);
}
} }
public void displayStatus(Cursor cursor, CursorIndices indices) { public void displayStatus(Cursor cursor, CursorIndices indices) {
final ImageLoaderWrapper loader = adapter.getImageLoader(); final ImageLoaderWrapper loader = adapter.getImageLoader();
final AsyncTwitterWrapper twitter = adapter.getTwitterWrapper();
final Context context = adapter.getContext(); final Context context = adapter.getContext();
final int reply_count = cursor.getInt(indices.reply_count); final int reply_count = cursor.getInt(indices.reply_count);
@ -178,6 +186,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements OnClick
final long account_id = cursor.getLong(indices.account_id); final long account_id = cursor.getLong(indices.account_id);
final long timestamp = cursor.getLong(indices.status_timestamp); final long timestamp = cursor.getLong(indices.status_timestamp);
final long user_id = cursor.getLong(indices.user_id); final long user_id = cursor.getLong(indices.user_id);
final long status_id = cursor.getLong(indices.status_id);
final long retweet_id = cursor.getLong(indices.retweet_id); final long retweet_id = cursor.getLong(indices.retweet_id);
final long my_retweet_id = cursor.getLong(indices.my_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 retweeted_by_id = cursor.getLong(indices.retweeted_by_user_id);
@ -269,6 +278,12 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements OnClick
retweetCountView.setEnabled(!user_is_protected); retweetCountView.setEnabled(!user_is_protected);
retweetCountView.setActivated(Utils.isMyRetweet(account_id, retweeted_by_id, my_retweet_id)); retweetCountView.setActivated(Utils.isMyRetweet(account_id, retweeted_by_id, my_retweet_id));
favoriteCountView.setActivated(cursor.getInt(indices.is_favorite) == 1); favoriteCountView.setActivated(cursor.getInt(indices.is_favorite) == 1);
if (twitter.isDestroyingFavorite(account_id, status_id)) {
favoriteCountView.setActivated(false);
} else {
favoriteCountView.setActivated(twitter.isCreatingFavorite(account_id, status_id)
|| cursor.getInt(indices.is_favorite) == 1);
}
} }
public CardView getCardView() { public CardView getCardView() {

View File

@ -42,387 +42,387 @@ import org.mariotaku.twidere.util.ThemeUtils;
public interface ICardItemView extends IColorLabelView { public interface ICardItemView extends IColorLabelView {
public View getFakeOverflowButton(); public View getFakeOverflowButton();
public boolean isGap(); public boolean isGap();
public void setActivatedIndicator(Drawable activatedIndicator); public void setActivatedIndicator(Drawable activatedIndicator);
public void setIsGap(boolean isGap); public void setIsGap(boolean isGap);
public void setItemBackground(Drawable itemBackground); public void setItemBackground(Drawable itemBackground);
public void setItemSelector(Drawable itemSelector); public void setItemSelector(Drawable itemSelector);
public void setOnOverflowIconClickListener(final OnOverflowIconClickListener listener); public void setOnOverflowIconClickListener(final OnOverflowIconClickListener listener);
public void setOverflowIcon(Drawable overflowIcon); public void setOverflowIcon(Drawable overflowIcon);
public static final class DrawingHelper { public static final class DrawingHelper {
private final View mView; private final View mView;
private final int mCardGapHeight; private final int mCardGapHeight;
private final String mCardGapText; private final String mCardGapText;
private final Paint mGapTextPaint; private final Paint mGapTextPaint;
private final Rect mGapTextBounds = new Rect(); private final Rect mGapTextBounds = new Rect();
private final Rect mBackgroundPadding = new Rect(); private final Rect mBackgroundPadding = new Rect();
private final Rect mOverflowIconBounds = new Rect(); private final Rect mOverflowIconBounds = new Rect();
private Drawable mBackground; private Drawable mBackground;
private Drawable mItemSelector; private Drawable mItemSelector;
private Drawable mActivatedIndicator; private Drawable mActivatedIndicator;
private Drawable mOverflowIcon; private Drawable mOverflowIcon;
private Drawable mPaddedOverflowIcon; private Drawable mPaddedOverflowIcon;
private boolean mIsGap; private boolean mIsGap;
private final int mThemeColor; private final int mThemeColor;
private final GestureDetector mOverflowIconGestureDetector; private final GestureDetector mOverflowIconGestureDetector;
private OnOverflowIconClickListener mOnOverflowIconClickListener; private OnOverflowIconClickListener mOnOverflowIconClickListener;
private final FakeOverflowButton mFakeOverflowButton; private final FakeOverflowButton mFakeOverflowButton;
private float mBackgroundAlpha; private float mBackgroundAlpha;
public DrawingHelper(final View view, final Context context, final AttributeSet attrs, final int defStyleAttr) { public DrawingHelper(final View view, final Context context, final AttributeSet attrs, final int defStyleAttr) {
mView = view; mView = view;
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CardItemView, defStyleAttr, final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CardItemView, defStyleAttr,
R.style.Widget_CardItemView); R.style.Widget_CardItemView);
mGapTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mGapTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCardGapHeight = a.getDimensionPixelSize(R.styleable.CardItemView_cardGapHeight, 0); mCardGapHeight = a.getDimensionPixelSize(R.styleable.CardItemView_cardGapHeight, 0);
mCardGapText = a.getString(R.styleable.CardItemView_cardGapText); mCardGapText = a.getString(R.styleable.CardItemView_cardGapText);
mGapTextPaint.setColor(a.getColor(R.styleable.CardItemView_cardGapTextColor, Color.GRAY)); mGapTextPaint.setColor(a.getColor(R.styleable.CardItemView_cardGapTextColor, Color.GRAY));
mGapTextPaint.setTextSize(a.getDimensionPixelSize(R.styleable.CardItemView_cardGapTextSize, 18)); mGapTextPaint.setTextSize(a.getDimensionPixelSize(R.styleable.CardItemView_cardGapTextSize, 18));
mGapTextPaint.setTypeface(Typeface.DEFAULT_BOLD); mGapTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
mThemeColor = ThemeUtils.getUserAccentColor(context); mThemeColor = view.isInEditMode() ? 0 : ThemeUtils.getUserAccentColor(context);
mOverflowIconGestureDetector = new GestureDetector(context, new OverflowIconGestureListener(this)); mOverflowIconGestureDetector = new GestureDetector(context, new OverflowIconGestureListener(this));
mFakeOverflowButton = new FakeOverflowButton(this); mFakeOverflowButton = new FakeOverflowButton(this);
mBackgroundAlpha = a.getFraction(R.styleable.CardItemView_cardBackgroundAlpha, 1, 1, 1.0f); mBackgroundAlpha = a.getFraction(R.styleable.CardItemView_cardBackgroundAlpha, 1, 1, 1.0f);
setItemBackground(a.getDrawable(R.styleable.CardItemView_cardBackground)); setItemBackground(a.getDrawable(R.styleable.CardItemView_cardBackground));
setItemSelector(a.getDrawable(R.styleable.CardItemView_cardSelector)); setItemSelector(a.getDrawable(R.styleable.CardItemView_cardSelector));
setActivatedIndicator(a.getDrawable(R.styleable.CardItemView_cardActivatedIndicator)); setActivatedIndicator(a.getDrawable(R.styleable.CardItemView_cardActivatedIndicator));
setOverflowIcon(a.getDrawable(R.styleable.CardItemView_cardOverflowIcon)); setOverflowIcon(a.getDrawable(R.styleable.CardItemView_cardOverflowIcon));
a.recycle(); a.recycle();
} }
public void dispatchDrawableStateChanged() { public void dispatchDrawableStateChanged() {
final int[] state = mView.getDrawableState(); final int[] state = mView.getDrawableState();
if (mBackground != null) { if (mBackground != null) {
mBackground.setState(state); mBackground.setState(state);
} }
if (mItemSelector != null) { if (mItemSelector != null) {
mItemSelector.setState(state); mItemSelector.setState(state);
} }
if (mActivatedIndicator != null) { if (mActivatedIndicator != null) {
mActivatedIndicator.setState(state); mActivatedIndicator.setState(state);
} }
} }
public void dispatchOnSizeChanged(final int w, final int h, final int oldw, final int oldh) { public void dispatchOnSizeChanged(final int w, final int h, final int oldw, final int oldh) {
final int paddingLeft = mView.getPaddingLeft(); final int paddingLeft = mView.getPaddingLeft();
final int paddingTop = mView.getPaddingTop(); final int paddingTop = mView.getPaddingTop();
final int paddingRight = mView.getPaddingRight(); final int paddingRight = mView.getPaddingRight();
final int paddingBottom = mView.getPaddingBottom(); final int paddingBottom = mView.getPaddingBottom();
final int l = paddingLeft, t = paddingTop, r = w - paddingRight, b = h - paddingBottom; final int l = paddingLeft, t = paddingTop, r = w - paddingRight, b = h - paddingBottom;
if (mBackground != null) { if (mBackground != null) {
if (mBackground instanceof NinePatchDrawable) { if (mBackground instanceof NinePatchDrawable) {
final NinePatchDrawable npd = (NinePatchDrawable) mBackground; final NinePatchDrawable npd = (NinePatchDrawable) mBackground;
npd.getPadding(mBackgroundPadding); npd.getPadding(mBackgroundPadding);
npd.setBounds(l - mBackgroundPadding.left, t - mBackgroundPadding.top, npd.setBounds(l - mBackgroundPadding.left, t - mBackgroundPadding.top,
r + mBackgroundPadding.right, b + mBackgroundPadding.bottom); r + mBackgroundPadding.right, b + mBackgroundPadding.bottom);
} else { } else {
mBackground.setBounds(l, t, r, b); mBackground.setBounds(l, t, r, b);
} }
} }
if (mItemSelector != null) { if (mItemSelector != null) {
if (mIsGap) { if (mIsGap) {
mItemSelector.setBounds(0, 0, w, h); mItemSelector.setBounds(0, 0, w, h);
} else { } else {
mItemSelector.setBounds(l, t, r, b); mItemSelector.setBounds(l, t, r, b);
} }
} }
if (mActivatedIndicator != null) { if (mActivatedIndicator != null) {
mActivatedIndicator.setBounds(l, t, r, b); mActivatedIndicator.setBounds(l, t, r, b);
} }
if (mOverflowIcon != null) { if (mOverflowIcon != null) {
mPaddedOverflowIcon = new PaddingDrawable(mOverflowIcon, paddingTop, 0, paddingRight, 0); mPaddedOverflowIcon = new PaddingDrawable(mOverflowIcon, paddingTop, 0, paddingRight, 0);
final int iw = mPaddedOverflowIcon.getIntrinsicWidth(); final int iw = mPaddedOverflowIcon.getIntrinsicWidth();
final int ih = mPaddedOverflowIcon.getIntrinsicHeight(); final int ih = mPaddedOverflowIcon.getIntrinsicHeight();
mOverflowIconBounds.set(w - iw, 0, w, ih); mOverflowIconBounds.set(w - iw, 0, w, ih);
mPaddedOverflowIcon.setBounds(mOverflowIconBounds); mPaddedOverflowIcon.setBounds(mOverflowIconBounds);
} else { } else {
mPaddedOverflowIcon = null; mPaddedOverflowIcon = null;
} }
} }
public void drawBackground(final Canvas canvas) { public void drawBackground(final Canvas canvas) {
if (mBackground != null && !mIsGap) { if (mBackground != null && !mIsGap) {
mBackground.draw(canvas); mBackground.draw(canvas);
} }
} }
public void drawGap(final Canvas canvas) { public void drawGap(final Canvas canvas) {
if (mIsGap) { if (mIsGap) {
final int centerX = canvas.getWidth() / 2, centerY = canvas.getHeight() / 2; final int centerX = canvas.getWidth() / 2, centerY = canvas.getHeight() / 2;
if (mCardGapText != null) { if (mCardGapText != null) {
mGapTextPaint.getTextBounds(mCardGapText, 0, mCardGapText.length(), mGapTextBounds); mGapTextPaint.getTextBounds(mCardGapText, 0, mCardGapText.length(), mGapTextBounds);
final float xPos = centerX - mGapTextBounds.width() / 2; final float xPos = centerX - mGapTextBounds.width() / 2;
final float yPos = centerY - (mGapTextPaint.descent() + mGapTextPaint.ascent()) / 2; final float yPos = centerY - (mGapTextPaint.descent() + mGapTextPaint.ascent()) / 2;
canvas.drawText(mCardGapText, xPos, yPos, mGapTextPaint); canvas.drawText(mCardGapText, xPos, yPos, mGapTextPaint);
} }
} }
} }
public void drawOverflowIcon(final Canvas canvas) { public void drawOverflowIcon(final Canvas canvas) {
if (mPaddedOverflowIcon != null && mOnOverflowIconClickListener != null) { if (mPaddedOverflowIcon != null && mOnOverflowIconClickListener != null) {
mPaddedOverflowIcon.draw(canvas); mPaddedOverflowIcon.draw(canvas);
} }
} }
public void drawSelector(final Canvas canvas) { public void drawSelector(final Canvas canvas) {
if (mActivatedIndicator != null) { if (mActivatedIndicator != null) {
mActivatedIndicator.draw(canvas); mActivatedIndicator.draw(canvas);
} }
if (mItemSelector != null) { if (mItemSelector != null) {
mItemSelector.draw(canvas); mItemSelector.draw(canvas);
} }
} }
public int getCardGapHeight() { public int getCardGapHeight() {
return mCardGapHeight; return mCardGapHeight;
} }
public View getFakeOverflowButton() { public View getFakeOverflowButton() {
return mFakeOverflowButton; return mFakeOverflowButton;
} }
public boolean handleOverflowTouchEvent(final MotionEvent ev) { public boolean handleOverflowTouchEvent(final MotionEvent ev) {
return mOverflowIconGestureDetector.onTouchEvent(ev); return mOverflowIconGestureDetector.onTouchEvent(ev);
} }
public boolean isGap() { public boolean isGap() {
return mIsGap; return mIsGap;
} }
public boolean isOverflowIconClicked(final MotionEvent ev) { public boolean isOverflowIconClicked(final MotionEvent ev) {
if (mOverflowIcon == null || mOnOverflowIconClickListener == null) return false; if (mOverflowIcon == null || mOnOverflowIconClickListener == null) return false;
final int x = Math.round(ev.getX()), y = Math.round(ev.getY()); final int x = Math.round(ev.getX()), y = Math.round(ev.getY());
if (mOverflowIconBounds.contains(x, y)) return true; if (mOverflowIconBounds.contains(x, y)) return true;
return false; return false;
} }
public void setActivatedIndicator(final Drawable activatedIndicator) { public void setActivatedIndicator(final Drawable activatedIndicator) {
preSetDrawable(mActivatedIndicator); preSetDrawable(mActivatedIndicator);
mActivatedIndicator = activatedIndicator; mActivatedIndicator = activatedIndicator;
if (activatedIndicator != null) { if (activatedIndicator != null) {
activatedIndicator.setAlpha(0x80); activatedIndicator.setAlpha(0x80);
} }
postSetDrawable(activatedIndicator); postSetDrawable(activatedIndicator);
} }
public void setIsGap(final boolean isGap) { public void setIsGap(final boolean isGap) {
mIsGap = isGap; mIsGap = isGap;
mView.requestLayout(); mView.requestLayout();
} }
public void setItemBackground(final Drawable itemBackground) { public void setItemBackground(final Drawable itemBackground) {
preSetDrawable(mBackground); preSetDrawable(mBackground);
mBackground = itemBackground; mBackground = itemBackground;
updateBackgroundAlpha(); updateBackgroundAlpha();
postSetDrawable(itemBackground); postSetDrawable(itemBackground);
} }
public void setItemBackgroundAlpha(final float alpha) { public void setItemBackgroundAlpha(final float alpha) {
mBackgroundAlpha = alpha; mBackgroundAlpha = alpha;
updateBackgroundAlpha(); updateBackgroundAlpha();
} }
public void setItemSelector(final Drawable itemSelector) { public void setItemSelector(final Drawable itemSelector) {
preSetDrawable(mItemSelector); preSetDrawable(mItemSelector);
mItemSelector = itemSelector; mItemSelector = itemSelector;
if (itemSelector != null) { if (itemSelector != null) {
itemSelector.setAlpha(0x80); itemSelector.setAlpha(0x80);
} }
postSetDrawable(itemSelector); postSetDrawable(itemSelector);
} }
public void setOnOverflowIconClickListener(final OnOverflowIconClickListener listener) { public void setOnOverflowIconClickListener(final OnOverflowIconClickListener listener) {
mOnOverflowIconClickListener = listener; mOnOverflowIconClickListener = listener;
} }
public void setOverflowIcon(final Drawable overflowIcon) { public void setOverflowIcon(final Drawable overflowIcon) {
preSetDrawable(mOverflowIcon); preSetDrawable(mOverflowIcon);
mOverflowIcon = overflowIcon; mOverflowIcon = overflowIcon;
if (mOverflowIcon != null) { if (mOverflowIcon != null) {
mOverflowIcon.mutate(); mOverflowIcon.mutate();
} }
postSetDrawable(overflowIcon); postSetDrawable(overflowIcon);
} }
public boolean verifyDrawable(final Drawable who) { public boolean verifyDrawable(final Drawable who) {
return who == mBackground || who == mItemSelector || who == mActivatedIndicator || who == mOverflowIcon; return who == mBackground || who == mItemSelector || who == mActivatedIndicator || who == mOverflowIcon;
} }
private void postSetDrawable(final Drawable curr) { private void postSetDrawable(final Drawable curr) {
mView.setWillNotDraw(verifyDrawable(curr)); mView.setWillNotDraw(verifyDrawable(curr));
if (curr != null) { if (curr != null) {
if (curr.isStateful()) { if (curr.isStateful()) {
curr.setState(mView.getDrawableState()); curr.setState(mView.getDrawableState());
} }
curr.setCallback(mView); curr.setCallback(mView);
} }
} }
private void preSetDrawable(final Drawable prev) { private void preSetDrawable(final Drawable prev) {
if (prev != null) { if (prev != null) {
mView.unscheduleDrawable(prev); mView.unscheduleDrawable(prev);
prev.setCallback(null); prev.setCallback(null);
} }
} }
private void updateBackgroundAlpha() { private void updateBackgroundAlpha() {
if (mBackground != null) { if (mBackground != null) {
mBackground.setAlpha(Math.round(mBackgroundAlpha * 0xff)); mBackground.setAlpha(Math.round(mBackgroundAlpha * 0xff));
} }
} }
static class FakeOverflowButton extends View { static class FakeOverflowButton extends View {
private final DrawingHelper mHelper; private final DrawingHelper mHelper;
public FakeOverflowButton(final DrawingHelper helper) { public FakeOverflowButton(final DrawingHelper helper) {
super(helper.mView.getContext()); super(helper.mView.getContext());
mHelper = helper; mHelper = helper;
} }
@Override @Override
public void getLocationInWindow(final int[] location) { public void getLocationInWindow(final int[] location) {
mHelper.mView.getLocationInWindow(location); mHelper.mView.getLocationInWindow(location);
location[0] += mHelper.mOverflowIconBounds.left; location[0] += mHelper.mOverflowIconBounds.left;
location[1] += mHelper.mOverflowIconBounds.top; location[1] += mHelper.mOverflowIconBounds.top;
} }
@Override @Override
public void getLocationOnScreen(final int[] location) { public void getLocationOnScreen(final int[] location) {
mHelper.mView.getLocationOnScreen(location); mHelper.mView.getLocationOnScreen(location);
location[0] += mHelper.mOverflowIconBounds.left; location[0] += mHelper.mOverflowIconBounds.left;
location[1] += mHelper.mOverflowIconBounds.top; location[1] += mHelper.mOverflowIconBounds.top;
} }
@Override @Override
public View getRootView() { public View getRootView() {
return mHelper.mView.getRootView(); return mHelper.mView.getRootView();
} }
@Override @Override
public Object getTag() { public Object getTag() {
return mHelper.mView.getTag(); return mHelper.mView.getTag();
} }
@Override @Override
public IBinder getWindowToken() { public IBinder getWindowToken() {
return mHelper.mView.getWindowToken(); return mHelper.mView.getWindowToken();
} }
@Override @Override
public void getWindowVisibleDisplayFrame(final Rect outRect) { public void getWindowVisibleDisplayFrame(final Rect outRect) {
mHelper.mView.getWindowVisibleDisplayFrame(outRect); mHelper.mView.getWindowVisibleDisplayFrame(outRect);
} }
@Override @Override
protected void onLayout(final boolean changed, final int left, final int top, final int right, protected void onLayout(final boolean changed, final int left, final int top, final int right,
final int bottom) { final int bottom) {
final Rect bounds = mHelper.mOverflowIconBounds; final Rect bounds = mHelper.mOverflowIconBounds;
layout(bounds.left, bounds.top, bounds.right, bounds.bottom); layout(bounds.left, bounds.top, bounds.right, bounds.bottom);
} }
@Override @Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
final int width = mHelper.mOverflowIconBounds.width(); final int width = mHelper.mOverflowIconBounds.width();
final int height = mHelper.mOverflowIconBounds.height(); final int height = mHelper.mOverflowIconBounds.height();
final int wSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.getMode(widthMeasureSpec)); final int wSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.getMode(widthMeasureSpec));
final int hSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.getMode(heightMeasureSpec)); final int hSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.getMode(heightMeasureSpec));
setMeasuredDimension(width, height); setMeasuredDimension(width, height);
super.onMeasure(wSpec, hSpec); super.onMeasure(wSpec, hSpec);
} }
} }
static class OverflowIconGestureListener extends SimpleOnGestureListener { static class OverflowIconGestureListener extends SimpleOnGestureListener {
private final DrawingHelper mDrawingHelper; private final DrawingHelper mDrawingHelper;
public OverflowIconGestureListener(final DrawingHelper drawingHelper) { public OverflowIconGestureListener(final DrawingHelper drawingHelper) {
mDrawingHelper = drawingHelper; mDrawingHelper = drawingHelper;
} }
@Override @Override
public boolean onDown(final MotionEvent e) { public boolean onDown(final MotionEvent e) {
final Drawable d = mDrawingHelper.mPaddedOverflowIcon; final Drawable d = mDrawingHelper.mPaddedOverflowIcon;
final OnOverflowIconClickListener l = mDrawingHelper.mOnOverflowIconClickListener; final OnOverflowIconClickListener l = mDrawingHelper.mOnOverflowIconClickListener;
if (d == null || l == null) return false; if (d == null || l == null) return false;
return true; return true;
} }
@Override @Override
public boolean onFling(final MotionEvent e1, final MotionEvent e2, final float velocityX, public boolean onFling(final MotionEvent e1, final MotionEvent e2, final float velocityX,
final float velocityY) { final float velocityY) {
return clearHighlight(); return clearHighlight();
} }
@Override @Override
public void onLongPress(final MotionEvent e) { public void onLongPress(final MotionEvent e) {
clearHighlight(); clearHighlight();
} }
@Override @Override
public boolean onScroll(final MotionEvent e1, final MotionEvent e2, final float distanceX, public boolean onScroll(final MotionEvent e1, final MotionEvent e2, final float distanceX,
final float distanceY) { final float distanceY) {
return clearHighlight(); return clearHighlight();
} }
@Override @Override
public void onShowPress(final MotionEvent e) { public void onShowPress(final MotionEvent e) {
final Drawable d = mDrawingHelper.mPaddedOverflowIcon; final Drawable d = mDrawingHelper.mPaddedOverflowIcon;
final int c = mDrawingHelper.mThemeColor; final int c = mDrawingHelper.mThemeColor;
if (d != null) { if (d != null) {
d.setColorFilter(c, PorterDuff.Mode.SRC_ATOP); d.setColorFilter(c, PorterDuff.Mode.SRC_ATOP);
} }
} }
@Override @Override
public boolean onSingleTapConfirmed(final MotionEvent e) { public boolean onSingleTapConfirmed(final MotionEvent e) {
final OnOverflowIconClickListener l = mDrawingHelper.mOnOverflowIconClickListener; final OnOverflowIconClickListener l = mDrawingHelper.mOnOverflowIconClickListener;
if (clearHighlight() && l != null) { if (clearHighlight() && l != null) {
l.onOverflowIconClick(mDrawingHelper.mFakeOverflowButton); l.onOverflowIconClick(mDrawingHelper.mFakeOverflowButton);
} }
return false; return false;
} }
@Override @Override
public boolean onSingleTapUp(final MotionEvent e) { public boolean onSingleTapUp(final MotionEvent e) {
return clearHighlight(); return clearHighlight();
} }
private boolean clearHighlight() { private boolean clearHighlight() {
final Drawable d = mDrawingHelper.mPaddedOverflowIcon; final Drawable d = mDrawingHelper.mPaddedOverflowIcon;
if (d != null) { if (d != null) {
d.clearColorFilter(); d.clearColorFilter();
return true; return true;
} }
return false; return false;
} }
} }
} }
public static interface OnOverflowIconClickListener { public static interface OnOverflowIconClickListener {
public void onOverflowIconClick(View view); public void onOverflowIconClick(View view);
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 452 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 468 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 468 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 565 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 413 B

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_card_item_message_incoming_normal_dark" android:state_window_focused="false"/>
<item android:drawable="@drawable/bg_card_item_message_incoming_pressed_dark" android:state_pressed="true" android:state_selected="true"/>
<item android:drawable="@drawable/bg_card_item_message_incoming_pressed_dark" android:state_pressed="true" android:state_selected="false"/>
<item android:drawable="@drawable/bg_card_item_message_incoming_focused_dark" android:state_selected="true"/>
</selector>

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_card_item_message_incoming_normal_light" android:state_window_focused="false"/>
<item android:drawable="@drawable/bg_card_item_message_incoming_pressed_light" android:state_pressed="true" android:state_selected="true"/>
<item android:drawable="@drawable/bg_card_item_message_incoming_pressed_light" android:state_pressed="true" android:state_selected="false"/>
<item android:drawable="@drawable/bg_card_item_message_incoming_focused_light" android:state_selected="true"/>
</selector>

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_card_item_message_incoming_pressed_dark"/>
<item android:drawable="@drawable/bg_card_item_message_incoming_longpressed_dark"/>
</transition>

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_card_item_message_incoming_pressed_light"/>
<item android:drawable="@drawable/bg_card_item_message_incoming_longpressed_light"/>
</transition>

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_card_item_message_outgoing_normal_dark" android:state_window_focused="false"/>
<item android:drawable="@drawable/bg_card_item_message_outgoing_pressed_dark" android:state_pressed="true" android:state_selected="true"/>
<item android:drawable="@drawable/bg_card_item_message_outgoing_pressed_dark" android:state_pressed="true" android:state_selected="false"/>
<item android:drawable="@drawable/bg_card_item_message_outgoing_focused_dark" android:state_selected="true"/>
</selector>

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_card_item_message_outgoing_normal_light" android:state_window_focused="false"/>
<item android:drawable="@drawable/bg_card_item_message_outgoing_pressed_light" android:state_pressed="true" android:state_selected="true"/>
<item android:drawable="@drawable/bg_card_item_message_outgoing_pressed_light" android:state_pressed="true" android:state_selected="false"/>
<item android:drawable="@drawable/bg_card_item_message_outgoing_focused_light" android:state_selected="true"/>
</selector>

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_card_item_message_outgoing_pressed_dark"/>
<item android:drawable="@drawable/bg_card_item_message_outgoing_longpressed_dark"/>
</transition>

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_card_item_message_outgoing_pressed_light"/>
<item android:drawable="@drawable/bg_card_item_message_outgoing_longpressed_light"/>
</transition>

View File

@ -2,6 +2,7 @@
<org.mariotaku.twidere.view.MainFrameLayout <org.mariotaku.twidere.view.MainFrameLayout
android:id="@+id/home_content" android:id="@+id/home_content"
xmlns:android="http://schemas.android.com/apk/res/android" 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_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -23,7 +24,9 @@
style="?android:actionBarStyle" style="?android:actionBarStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?android:actionBarSize" android:layout_height="?android:actionBarSize"
android:layout_weight="0"/> android:layout_weight="0"
app:tabExpandEnabled="true"
app:tabHorizontalPadding="@dimen/element_spacing_normal"/>
<View <View
android:id="@+id/actionbar_overlay" android:id="@+id/actionbar_overlay"

View File

@ -25,13 +25,14 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<com.astuetz.PagerSlidingTabStrip <org.mariotaku.twidere.view.TabPagerIndicator
android:id="@+id/view_pager_tabs" android:id="@+id/view_pager_tabs"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/element_size_normal" android:layout_height="@dimen/element_size_normal"
android:textColor="?android:textColorSecondary" android:textColor="?android:textColorSecondary"
app:pstsTabBackground="?android:selectableItemBackground" app:tabHorizontalPadding="@dimen/element_spacing_large"
app:pstsTabPaddingLeftRight="@dimen/element_spacing_large"/> app:tabExpandEnabled="false"
app:tabIconColor="?android:colorForeground"/>
<android.support.v4.view.ViewPager <android.support.v4.view.ViewPager
android:id="@+id/view_pager" android:id="@+id/view_pager"

View File

@ -112,13 +112,20 @@
<org.mariotaku.twidere.view.themed.ThemedTextView <org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="@dimen/element_spacing_small"
android:singleLine="true"
android:text="@string/description" android:text="@string/description"
android:textAppearance="?android:textAppearanceMedium"/> android:textAllCaps="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:textColorPrimary"
android:textStyle="bold"/>
<org.mariotaku.twidere.view.HandleSpanClickTextView <org.mariotaku.twidere.view.HandleSpanClickTextView
android:id="@+id/description" android:id="@+id/description"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="@dimen/element_spacing_small"
android:paddingRight="@dimen/element_spacing_small"
android:textAppearance="?android:textAppearanceSmall" android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/> android:textColor="?android:textColorSecondary"/>
</LinearLayout> </LinearLayout>
@ -135,14 +142,20 @@
<org.mariotaku.twidere.view.themed.ThemedTextView <org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="@dimen/element_spacing_small"
android:singleLine="true" android:singleLine="true"
android:text="@string/location" android:text="@string/location"
android:textAppearance="?android:textAppearanceMedium"/> android:textAllCaps="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:textColorPrimary"
android:textStyle="bold"/>
<org.mariotaku.twidere.view.themed.ThemedTextView <org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/location" android:id="@+id/location"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="@dimen/element_spacing_small"
android:paddingRight="@dimen/element_spacing_small"
android:singleLine="true" android:singleLine="true"
android:textAppearance="?android:textAppearanceSmall" android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/> android:textColor="?android:textColorSecondary"/>
@ -160,15 +173,21 @@
<org.mariotaku.twidere.view.themed.ThemedTextView <org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="@dimen/element_spacing_small"
android:singleLine="true" android:singleLine="true"
android:text="@string/url" android:text="@string/url"
android:textAppearance="?android:textAppearanceMedium"/> android:textAllCaps="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:textColorPrimary"
android:textStyle="bold"/>
<org.mariotaku.twidere.view.HandleSpanClickTextView <org.mariotaku.twidere.view.HandleSpanClickTextView
android:id="@+id/url" android:id="@+id/url"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:autoLink="web" android:autoLink="web"
android:paddingLeft="@dimen/element_spacing_small"
android:paddingRight="@dimen/element_spacing_small"
android:singleLine="true" android:singleLine="true"
android:textAppearance="?android:textAppearanceSmall" android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/> android:textColor="?android:textColorSecondary"/>
@ -184,16 +203,22 @@
android:padding="@dimen/element_spacing_small"> android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView <org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="@dimen/element_spacing_small"
android:singleLine="true" android:singleLine="true"
android:text="@string/created_at" android:text="@string/created_at"
android:textAppearance="?android:textAppearanceMedium"/> android:textAllCaps="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:textColorPrimary"
android:textStyle="bold"/>
<org.mariotaku.twidere.view.themed.ThemedTextView <org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/created_at" android:id="@+id/created_at"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="@dimen/element_spacing_small"
android:paddingRight="@dimen/element_spacing_small"
android:singleLine="true" android:singleLine="true"
android:textAppearance="?android:textAppearanceSmall" android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/> android:textColor="?android:textColorSecondary"/>
@ -332,7 +357,7 @@
android:alpha="0.2" android:alpha="0.2"
android:gravity="center" android:gravity="center"
android:padding="@dimen/element_spacing_small" android:padding="@dimen/element_spacing_small"
android:text="- Luna meae es -" android:text="@string/uucky_footer_text"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
android:textSize="10sp" android:textSize="10sp"
android:textStyle="italic" android:textStyle="italic"

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<view
class="org.mariotaku.twidere.view.TabPagerIndicator$ItemLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="?android:selectableItemBackground">
<LinearLayout
android:id="@+id/tab_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/tab_icon"
android:layout_width="@dimen/action_icon_size"
android:layout_height="@dimen/action_icon_size"
android:contentDescription="@string/icon"
android:scaleType="centerInside"/>
<TextView
android:id="@+id/tab_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="true"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorPrimary"
android:textStyle="bold"/>
</LinearLayout>
<org.mariotaku.twidere.view.BadgeView
android:id="@+id/unread_indicator"
android:layout_width="@dimen/unread_indicator_size"
android:layout_height="@dimen/unread_indicator_size"
android:layout_alignRight="@+id/tab_content"
android:layout_alignTop="@+id/tab_content"
android:layout_marginRight="@dimen/element_spacing_minus_small"
android:layout_marginTop="@dimen/element_spacing_minus_small"
android:background="@drawable/bg_unread_indicator"
android:ellipsize="none"
android:gravity="center"
android:padding="@dimen/element_spacing_xsmall"
android:singleLine="true"
android:textColor="?android:textColorPrimary"/>
</view>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<me.imid.swipebacklayout.lib.SwipeBackLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipe"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:selectableItemBackground">
<View
android:id="@+id/selected_indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:background="?android:activatedBackgroundIndicator"/>
<ImageView
android:id="@+id/tab_icon"
android:layout_width="@dimen/action_icon_size"
android:layout_height="@dimen/action_icon_size"
android:layout_centerInParent="true"
android:scaleType="centerInside"/>
<org.mariotaku.twidere.view.BadgeView
android:id="@+id/unread_indicator"
android:layout_width="@dimen/unread_indicator_size"
android:layout_height="@dimen/unread_indicator_size"
android:layout_alignRight="@+id/tab_icon"
android:layout_alignTop="@+id/tab_icon"
android:layout_marginRight="@dimen/element_spacing_minus_small"
android:layout_marginTop="@dimen/element_spacing_minus_small"
android:background="@drawable/bg_unread_indicator"
android:ellipsize="none"
android:gravity="center"
android:padding="@dimen/element_spacing_xsmall"
android:singleLine="true"
android:textColor="?android:textColorPrimary"/>
</RelativeLayout>

View File

@ -29,6 +29,7 @@
<autoTransition> <autoTransition>
<targets> <targets>
<target android:targetId="@id/profile_banner"/> <target android:targetId="@id/profile_banner"/>
<target android:targetId="@id/view_pager_tabs"/>
</targets> </targets>
</autoTransition> </autoTransition>
</transitionSet> </transitionSet>

View File

@ -11,10 +11,6 @@
<attr name="messageBubbleColor" format="color"/> <attr name="messageBubbleColor" format="color"/>
<attr name="cardItemBackground" format="reference"/> <attr name="cardItemBackground" format="reference"/>
<attr name="cardItemBackgroundColor" format="color"/> <attr name="cardItemBackgroundColor" format="color"/>
<attr name="cardItemMessageIncomingBackground" format="reference"/>
<attr name="cardItemMessageOutgoingBackground" format="reference"/>
<attr name="cardItemMessageProfileImageIncomingBackground" format="reference"/>
<attr name="cardItemMessageProfileImageOutgoingBackground" format="reference"/>
<attr name="listMenuOverflowButton" format="reference"/> <attr name="listMenuOverflowButton" format="reference"/>
<attr name="ignorePadding" format="boolean"/> <attr name="ignorePadding" format="boolean"/>
<attr name="linePageIndicatorStyle" format="reference"/> <attr name="linePageIndicatorStyle" format="reference"/>
@ -32,9 +28,12 @@
<attr name="cardGapTextSize" format="dimension"/> <attr name="cardGapTextSize" format="dimension"/>
</declare-styleable> </declare-styleable>
<declare-styleable name="TabPagerIndicator"> <declare-styleable name="TabPagerIndicator">
<attr name="tabItemStyle" format="reference"/> <attr name="tabStripColor" format="color"/>
<attr name="tabItemContentStyle" format="reference"/> <attr name="tabIconColor" format="color"/>
<attr name="tabItemTextStyle" format="reference"/> <attr name="tabHorizontalPadding" format="dimension"/>
<attr name="tabVerticalPadding" format="dimension"/>
<attr name="tabExpandEnabled" format="boolean"/>
<attr name="tabDisplayOption"/>
</declare-styleable> </declare-styleable>
<declare-styleable name="LinePageIndicator"> <declare-styleable name="LinePageIndicator">
<!-- Whether or not the indicators should be centered. --> <!-- Whether or not the indicators should be centered. -->
@ -94,5 +93,8 @@
<flag name="vibration" value="2"/> <flag name="vibration" value="2"/>
<flag name="light" value="4"/> <flag name="light" value="4"/>
</attr> </attr>
<attr name="tabDisplayOption">
<flag name="label" value="0x1"/>
<flag name="icon" value="0x2"/>
</attr>
</resources> </resources>

View File

@ -12,5 +12,6 @@
<string name="font_family_light" translatable="false">Light</string> <string name="font_family_light" translatable="false">Light</string>
<string name="font_family_thin" translatable="false">Thin</string> <string name="font_family_thin" translatable="false">Thin</string>
<string name="easter_egg_triggered_message" translatable="false">不二对你的膝盖发动了会心一击!</string> <string name="easter_egg_triggered_message" translatable="false">不二对你的膝盖发动了会心一击!</string>
<string name="uucky_footer_text">- Luna meae es -</string>
</resources> </resources>

View File

@ -30,27 +30,12 @@
</item> </item>
<!-- Custom view styles --> <!-- Custom view styles -->
<item name="tabItemStyle">@style/Widget.TabPageIndicator.TabItem</item>
<item name="tabItemContentStyle">@style/Widget.TabPageIndicator.TabItem.Content</item>
<item name="tabItemTextStyle">@style/Widget.TabPageIndicator.TabItem.TextView.Dark</item>
<!-- Card UI styles --> <!-- Card UI styles -->
<item name="cardActionButtonStyle">@style/Widget.CardActionButton</item> <item name="cardActionButtonStyle">@style/Widget.CardActionButton</item>
<item name="profileImageStyleLarge">@style/Widget.ProfileImage.Large</item> <item name="profileImageStyleLarge">@style/Widget.ProfileImage.Large</item>
<item name="cardItemBackground">@drawable/bg_card_item_dark</item> <item name="cardItemBackground">@drawable/bg_card_item_dark</item>
<item name="cardItemBackgroundColor">#1a1a1a</item> <item name="cardItemBackgroundColor">#1a1a1a</item>
<item name="cardItemMessageIncomingBackground">
@drawable/bg_card_item_message_incoming_dark
</item>
<item name="cardItemMessageOutgoingBackground">
@drawable/bg_card_item_message_outgoing_dark
</item>
<item name="cardItemMessageProfileImageIncomingBackground">
@drawable/bg_card_item_message_profile_image_incoming_dark
</item>
<item name="cardItemMessageProfileImageOutgoingBackground">
@drawable/bg_card_item_message_profile_image_outgoing_dark
</item>
<item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_dark <item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_dark
</item> </item>
<item name="cardItemViewStyle">@style/Widget.CardItemView</item> <item name="cardItemViewStyle">@style/Widget.CardItemView</item>
@ -75,33 +60,15 @@
<!--<item name="android:actionBarWidgetTheme">@style/Theme.Twidere.Dark</item>--> <!--<item name="android:actionBarWidgetTheme">@style/Theme.Twidere.Dark</item>-->
<!-- Custom view styles --> <!-- Custom view styles -->
<item name="tabItemStyle">@style/Widget.TabPageIndicator.TabItem</item>
<item name="tabItemContentStyle">@style/Widget.TabPageIndicator.TabItem.Content</item>
<item name="tabItemTextStyle">
@style/Widget.TabPageIndicator.TabItem.TextView.Light.DarkActionBar
</item>
<!-- Card UI styles --> <!-- Card UI styles -->
<item name="cardActionButtonStyle">@style/Widget.Light.CardActionButton</item> <item name="cardActionButtonStyle">@style/Widget.Light.CardActionButton</item>
<item name="profileImageStyleLarge">@style/Widget.Light.ProfileImage.Large</item> <item name="profileImageStyleLarge">@style/Widget.Light.ProfileImage.Large</item>
<item name="cardItemBackground">@drawable/bg_card_item_light</item> <item name="cardItemBackground">@drawable/bg_card_item_light</item>
<item name="cardItemBackgroundColor">#f8f8f8</item> <item name="cardItemBackgroundColor">#f8f8f8</item>
<item name="cardItemMessageIncomingBackground">
@drawable/bg_card_item_message_incoming_light
</item>
<item name="cardItemMessageOutgoingBackground">
@drawable/bg_card_item_message_outgoing_light
</item>
<item name="cardItemMessageProfileImageIncomingBackground">
@drawable/bg_card_item_message_profile_image_incoming_light
</item>
<item name="cardItemMessageProfileImageOutgoingBackground">
@drawable/bg_card_item_message_profile_image_outgoing_light
</item>
<item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_light <item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_light
</item> </item>
<item name="cardItemViewStyle">@style/Widget.CardItemView.Light</item> <item name="cardItemViewStyle">@style/Widget.CardItemView.Light</item>
<!-- Twidere specific styles --> <!-- Twidere specific styles -->
<item name="menuIconColor">@color/action_icon_dark</item> <item name="menuIconColor">@color/action_icon_dark</item>
<item name="menuIconColorDisabled">@color/action_icon_dark_disabled</item> <item name="menuIconColorDisabled">@color/action_icon_dark_disabled</item>
@ -153,27 +120,13 @@
<style name="Theme.Twidere.Dark.Dialog" parent="Theme.Base.Dialog"> <style name="Theme.Twidere.Dark.Dialog" parent="Theme.Base.Dialog">
<!-- Custom view styles --> <!-- Custom view styles -->
<item name="tabItemStyle">@style/Widget.TabPageIndicator.TabItem</item>
<item name="tabItemContentStyle">@style/Widget.TabPageIndicator.TabItem.Content</item>
<item name="tabItemTextStyle">@style/Widget.TabPageIndicator.TabItem.TextView</item>
<!-- Card UI styles --> <!-- Card UI styles -->
<item name="cardActionButtonStyle">@style/Widget.CardActionButton</item> <item name="cardActionButtonStyle">@style/Widget.CardActionButton</item>
<item name="profileImageStyleLarge">@style/Widget.ProfileImage.Large</item> <item name="profileImageStyleLarge">@style/Widget.ProfileImage.Large</item>
<item name="cardItemBackground">@drawable/bg_card_item_dark</item> <item name="cardItemBackground">@drawable/bg_card_item_dark</item>
<item name="cardItemBackgroundColor">#1a1a1a</item> <item name="cardItemBackgroundColor">#1a1a1a</item>
<item name="cardItemMessageIncomingBackground">
@drawable/bg_card_item_message_incoming_dark
</item>
<item name="cardItemMessageOutgoingBackground">
@drawable/bg_card_item_message_outgoing_dark
</item>
<item name="cardItemMessageProfileImageIncomingBackground">
@drawable/bg_card_item_message_profile_image_incoming_dark
</item>
<item name="cardItemMessageProfileImageOutgoingBackground">
@drawable/bg_card_item_message_profile_image_outgoing_dark
</item>
<item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_dark <item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_dark
</item> </item>
<item name="cardItemViewStyle">@style/Widget.CardItemView</item> <item name="cardItemViewStyle">@style/Widget.CardItemView</item>
@ -187,27 +140,13 @@
<style name="Theme.Twidere.Light.Dialog" parent="Theme.Base.Light.Dialog"> <style name="Theme.Twidere.Light.Dialog" parent="Theme.Base.Light.Dialog">
<!-- Custom view styles --> <!-- Custom view styles -->
<item name="tabItemStyle">@style/Widget.TabPageIndicator.TabItem</item>
<item name="tabItemContentStyle">@style/Widget.TabPageIndicator.TabItem.Content</item>
<item name="tabItemTextStyle">@style/Widget.TabPageIndicator.TabItem.TextView</item>
<!-- Card UI styles --> <!-- Card UI styles -->
<item name="cardActionButtonStyle">@style/Widget.Light.CardActionButton</item> <item name="cardActionButtonStyle">@style/Widget.Light.CardActionButton</item>
<item name="profileImageStyleLarge">@style/Widget.Light.ProfileImage.Large</item> <item name="profileImageStyleLarge">@style/Widget.Light.ProfileImage.Large</item>
<item name="cardItemBackground">@drawable/bg_card_item_light</item> <item name="cardItemBackground">@drawable/bg_card_item_light</item>
<item name="cardItemBackgroundColor">#f8f8f8</item> <item name="cardItemBackgroundColor">#f8f8f8</item>
<item name="cardItemMessageIncomingBackground">
@drawable/bg_card_item_message_incoming_light
</item>
<item name="cardItemMessageOutgoingBackground">
@drawable/bg_card_item_message_outgoing_light
</item>
<item name="cardItemMessageProfileImageIncomingBackground">
@drawable/bg_card_item_message_profile_image_incoming_light
</item>
<item name="cardItemMessageProfileImageOutgoingBackground">
@drawable/bg_card_item_message_profile_image_outgoing_light
</item>
<item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_light <item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_light
</item> </item>
<item name="cardItemViewStyle">@style/Widget.CardItemView.Light</item> <item name="cardItemViewStyle">@style/Widget.CardItemView.Light</item>
@ -258,18 +197,6 @@
<item name="profileImageStyleLarge">@style/Widget.ProfileImage.Large</item> <item name="profileImageStyleLarge">@style/Widget.ProfileImage.Large</item>
<item name="cardItemBackground">@drawable/bg_card_item_dark</item> <item name="cardItemBackground">@drawable/bg_card_item_dark</item>
<item name="cardItemBackgroundColor">#1a1a1a</item> <item name="cardItemBackgroundColor">#1a1a1a</item>
<item name="cardItemMessageIncomingBackground">
@drawable/bg_card_item_message_incoming_dark
</item>
<item name="cardItemMessageOutgoingBackground">
@drawable/bg_card_item_message_outgoing_dark
</item>
<item name="cardItemMessageProfileImageIncomingBackground">
@drawable/bg_card_item_message_profile_image_incoming_dark
</item>
<item name="cardItemMessageProfileImageOutgoingBackground">
@drawable/bg_card_item_message_profile_image_outgoing_dark
</item>
<item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_dark <item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_dark
</item> </item>
<item name="cardItemViewStyle">@style/Widget.CardItemView</item> <item name="cardItemViewStyle">@style/Widget.CardItemView</item>
@ -351,27 +278,12 @@
</item> </item>
<!-- Custom view styles --> <!-- Custom view styles -->
<item name="tabItemStyle">@style/Widget.TabPageIndicator.TabItem</item>
<item name="tabItemContentStyle">@style/Widget.TabPageIndicator.TabItem.Content</item>
<item name="tabItemTextStyle">@style/Widget.TabPageIndicator.TabItem.TextView.Dark</item>
<!-- Card UI styles --> <!-- Card UI styles -->
<item name="cardActionButtonStyle">@style/Widget.CardActionButton</item> <item name="cardActionButtonStyle">@style/Widget.CardActionButton</item>
<item name="profileImageStyleLarge">@style/Widget.ProfileImage.Large</item> <item name="profileImageStyleLarge">@style/Widget.ProfileImage.Large</item>
<item name="cardItemBackground">@drawable/bg_card_item_dark</item> <item name="cardItemBackground">@drawable/bg_card_item_dark</item>
<item name="cardItemBackgroundColor">#1a1a1a</item> <item name="cardItemBackgroundColor">#1a1a1a</item>
<item name="cardItemMessageIncomingBackground">
@drawable/bg_card_item_message_incoming_dark
</item>
<item name="cardItemMessageOutgoingBackground">
@drawable/bg_card_item_message_outgoing_dark
</item>
<item name="cardItemMessageProfileImageIncomingBackground">
@drawable/bg_card_item_message_profile_image_incoming_dark
</item>
<item name="cardItemMessageProfileImageOutgoingBackground">
@drawable/bg_card_item_message_profile_image_outgoing_dark
</item>
<item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_dark <item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_dark
</item> </item>
<item name="cardItemViewStyle">@style/Widget.CardItemView</item> <item name="cardItemViewStyle">@style/Widget.CardItemView</item>
@ -392,27 +304,12 @@
<!--<item name="android:windowBackground">@color/bg_color_light</item>--> <!--<item name="android:windowBackground">@color/bg_color_light</item>-->
<!-- Custom view styles --> <!-- Custom view styles -->
<item name="tabItemStyle">@style/Widget.TabPageIndicator.TabItem</item>
<item name="tabItemContentStyle">@style/Widget.TabPageIndicator.TabItem.Content</item>
<item name="tabItemTextStyle">@style/Widget.TabPageIndicator.TabItem.TextView.Light</item>
<!-- Card UI styles --> <!-- Card UI styles -->
<item name="cardActionButtonStyle">@style/Widget.Light.CardActionButton</item> <item name="cardActionButtonStyle">@style/Widget.Light.CardActionButton</item>
<item name="profileImageStyleLarge">@style/Widget.Light.ProfileImage.Large</item> <item name="profileImageStyleLarge">@style/Widget.Light.ProfileImage.Large</item>
<item name="cardItemBackground">@drawable/bg_card_item_light</item> <item name="cardItemBackground">@drawable/bg_card_item_light</item>
<item name="cardItemBackgroundColor">#f8f8f8</item> <item name="cardItemBackgroundColor">#f8f8f8</item>
<item name="cardItemMessageIncomingBackground">
@drawable/bg_card_item_message_incoming_light
</item>
<item name="cardItemMessageOutgoingBackground">
@drawable/bg_card_item_message_outgoing_light
</item>
<item name="cardItemMessageProfileImageIncomingBackground">
@drawable/bg_card_item_message_profile_image_incoming_light
</item>
<item name="cardItemMessageProfileImageOutgoingBackground">
@drawable/bg_card_item_message_profile_image_outgoing_light
</item>
<item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_light <item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_light
</item> </item>
<item name="cardItemViewStyle">@style/Widget.CardItemView.Light</item> <item name="cardItemViewStyle">@style/Widget.CardItemView.Light</item>
@ -433,27 +330,12 @@
<!--<item name="android:windowBackground">@color/bg_color_light</item>--> <!--<item name="android:windowBackground">@color/bg_color_light</item>-->
<!-- Custom view styles --> <!-- Custom view styles -->
<item name="tabItemStyle">@style/Widget.TabPageIndicator.TabItem</item>
<item name="tabItemContentStyle">@style/Widget.TabPageIndicator.TabItem.Content</item>
<item name="tabItemTextStyle">@style/Widget.TabPageIndicator.TabItem.TextView.Light</item>
<!-- Card UI styles --> <!-- Card UI styles -->
<item name="cardActionButtonStyle">@style/Widget.Light.CardActionButton</item> <item name="cardActionButtonStyle">@style/Widget.Light.CardActionButton</item>
<item name="profileImageStyleLarge">@style/Widget.Light.ProfileImage.Large</item> <item name="profileImageStyleLarge">@style/Widget.Light.ProfileImage.Large</item>
<item name="cardItemBackground">@drawable/bg_card_item_light</item> <item name="cardItemBackground">@drawable/bg_card_item_light</item>
<item name="cardItemBackgroundColor">#f8f8f8</item> <item name="cardItemBackgroundColor">#f8f8f8</item>
<item name="cardItemMessageIncomingBackground">
@drawable/bg_card_item_message_incoming_light
</item>
<item name="cardItemMessageOutgoingBackground">
@drawable/bg_card_item_message_outgoing_light
</item>
<item name="cardItemMessageProfileImageIncomingBackground">
@drawable/bg_card_item_message_profile_image_incoming_light
</item>
<item name="cardItemMessageProfileImageOutgoingBackground">
@drawable/bg_card_item_message_profile_image_outgoing_light
</item>
<item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_light <item name="listMenuOverflowButton">@drawable/ic_list_menu_moreoverflow_normal_holo_light
</item> </item>
<item name="cardItemViewStyle">@style/Widget.CardItemView.Light</item> <item name="cardItemViewStyle">@style/Widget.CardItemView.Light</item>