From dd729d2d5cd9c2e24364ce9a9b14be5c1d4afb64 Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Wed, 1 Apr 2015 21:42:07 +0800 Subject: [PATCH] improved search ui fixed notification light/vibrate/ringtone option improved refresh indicator in statuses timeline fixed crashes when open drafts fixed annoying loading indicator always visible on screen --- .../java/org/mariotaku/twidere/Constants.java | 2 +- .../twidere/adapter/AbsActivitiesAdapter.java | 36 +++++-- .../twidere/adapter/AbsStatusesAdapter.java | 99 +++++++++++-------- .../adapter/CursorStatusesAdapter.java | 2 +- .../adapter/MessageEntriesAdapter.java | 35 +++++-- .../adapter/iface/IContentCardAdapter.java | 8 +- .../support/AbsActivitiesFragment.java | 4 +- .../fragment/support/AbsStatusesFragment.java | 22 ++++- .../support/CursorStatusesFragment.java | 10 ++ .../support/DirectMessagesFragment.java | 32 +++--- .../support/ParcelableStatusesFragment.java | 9 ++ .../fragment/support/StatusFragment.java | 26 ++++- .../twidere/util/AsyncTwitterWrapper.java | 20 +++- .../util/ContentListScrollListener.java | 3 +- .../util/content/TwidereSQLiteOpenHelper.java | 18 ++++ .../util/message/GetMessagesTaskEvent.java | 38 +++++++ twidere/src/main/res/values/colors.xml | 6 +- twidere/src/main/res/values/themes.xml | 28 +++--- 18 files changed, 295 insertions(+), 103 deletions(-) create mode 100644 twidere/src/main/java/org/mariotaku/twidere/util/message/GetMessagesTaskEvent.java diff --git a/twidere/src/main/java/org/mariotaku/twidere/Constants.java b/twidere/src/main/java/org/mariotaku/twidere/Constants.java index 6ea318e89..c86451142 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/Constants.java +++ b/twidere/src/main/java/org/mariotaku/twidere/Constants.java @@ -33,7 +33,7 @@ import static org.mariotaku.twidere.annotation.Preference.Type.STRING; public interface Constants extends TwidereConstants { String DATABASES_NAME = "twidere.sqlite"; - int DATABASES_VERSION = 89; + int DATABASES_VERSION = 90; int MENU_GROUP_STATUS_EXTENSION = 10; int MENU_GROUP_COMPOSE_EXTENSION = 11; diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/AbsActivitiesAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/AbsActivitiesAdapter.java index 5c759ef05..8db87e42d 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/AbsActivitiesAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/AbsActivitiesAdapter.java @@ -75,7 +75,8 @@ public abstract class AbsActivitiesAdapter extends Adapter imp private final boolean mDisplayMediaPreview; private final boolean mNameFirst; private final boolean mDisplayProfileImage; - private boolean mLoadMoreIndicatorEnabled; + private boolean mLoadMoreSupported; + private boolean mLoadMoreIndicatorVisible; private ActivityAdapterListener mActivityAdapterListener; protected AbsActivitiesAdapter(final Context context, boolean compact) { @@ -140,10 +141,6 @@ public abstract class AbsActivitiesAdapter extends Adapter imp return mTextSize; } - public boolean hasLoadMoreIndicator() { - return mLoadMoreIndicatorEnabled; - } - public boolean isNameFirst() { return mNameFirst; } @@ -248,7 +245,7 @@ public abstract class AbsActivitiesAdapter extends Adapter imp } public final int getItemCount() { - return getActivityCount() + (mLoadMoreIndicatorEnabled ? 1 : 0); + return getActivityCount() + (mLoadMoreIndicatorVisible ? 1 : 0); } @Override @@ -313,12 +310,33 @@ public abstract class AbsActivitiesAdapter extends Adapter imp mActivityAdapterListener = listener; } - public void setLoadMoreIndicatorEnabled(boolean enabled) { - if (mLoadMoreIndicatorEnabled == enabled) return; - mLoadMoreIndicatorEnabled = enabled; + @Override + public boolean isLoadMoreIndicatorVisible() { + return mLoadMoreIndicatorVisible; + } + + @Override + public boolean isLoadMoreSupported() { + return mLoadMoreSupported; + } + + @Override + public void setLoadMoreSupported(boolean supported) { + mLoadMoreSupported = supported; + if (!supported) { + mLoadMoreIndicatorVisible = false; + } notifyDataSetChanged(); } + @Override + public void setLoadMoreIndicatorVisible(boolean enabled) { + if (mLoadMoreIndicatorVisible == enabled) return; + mLoadMoreIndicatorVisible = enabled && mLoadMoreSupported; + notifyDataSetChanged(); + } + + protected abstract void bindTitleSummaryViewHolder(ActivityTitleSummaryViewHolder holder, int position); protected abstract int getActivityAction(int position); diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/AbsStatusesAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/AbsStatusesAdapter.java index ec652e491..672aac5d6 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/AbsStatusesAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/AbsStatusesAdapter.java @@ -33,11 +33,11 @@ import org.mariotaku.twidere.view.holder.StatusViewHolder; */ public abstract class AbsStatusesAdapter extends Adapter implements Constants, IStatusesAdapter { - public static final int ITEM_VIEW_TYPE_STATUS = 0; public static final int ITEM_VIEW_TYPE_GAP = 1; public static final int ITEM_VIEW_TYPE_LOAD_INDICATOR = 2; + private final Context mContext; private final LayoutInflater mInflater; private final MediaLoaderWrapper mImageLoader; @@ -46,11 +46,15 @@ public abstract class AbsStatusesAdapter extends Adapter implemen private final int mCardBackgroundColor; private final int mTextSize; private final int mProfileImageStyle, mMediaPreviewStyle; + private final boolean mCompactCards; private final boolean mNameFirst; private final boolean mDisplayMediaPreview; private final boolean mDisplayProfileImage; - private boolean mLoadMoreIndicatorEnabled; + + private boolean mLoadMoreSupported; + private boolean mLoadMoreIndicatorVisible; + private StatusAdapterListener mStatusAdapterListener; private boolean mShowInReplyTo; private boolean mShowAccountsColor; @@ -120,14 +124,28 @@ public abstract class AbsStatusesAdapter extends Adapter implemen } @Override - public boolean hasLoadMoreIndicator() { - return mLoadMoreIndicatorEnabled; + public boolean isLoadMoreIndicatorVisible() { + return mLoadMoreIndicatorVisible; } @Override - public void setLoadMoreIndicatorEnabled(boolean enabled) { - if (mLoadMoreIndicatorEnabled == enabled) return; - mLoadMoreIndicatorEnabled = enabled; + public boolean isLoadMoreSupported() { + return mLoadMoreSupported; + } + + @Override + public void setLoadMoreSupported(boolean supported) { + mLoadMoreSupported = supported; + if (!supported) { + mLoadMoreIndicatorVisible = false; + } + notifyDataSetChanged(); + } + + @Override + public void setLoadMoreIndicatorVisible(boolean enabled) { + if (mLoadMoreIndicatorVisible == enabled) return; + mLoadMoreIndicatorVisible = enabled && mLoadMoreSupported; notifyDataSetChanged(); } @@ -136,14 +154,44 @@ public abstract class AbsStatusesAdapter extends Adapter implemen return mDisplayMediaPreview; } + @Override + public boolean isNameFirst() { + return mNameFirst; + } + @Override public boolean isProfileImageEnabled() { return mDisplayProfileImage; } @Override - public boolean isNameFirst() { - return mNameFirst; + public final void onStatusClick(StatusViewHolder holder, int position) { + if (mStatusAdapterListener != null) { + mStatusAdapterListener.onStatusClick(holder, position); + } + } + + @Override + public void onMediaClick(StatusViewHolder holder, ParcelableMedia media, int position) { + if (mStatusAdapterListener != null) { + mStatusAdapterListener.onMediaClick(holder, media, position); + } + } + + @Override + public void onUserProfileClick(StatusViewHolder holder, int position) { + final Context context = getContext(); + final ParcelableStatus status = getStatus(position); + final View profileImageView = holder.getProfileImageView(); + final View profileTypeView = holder.getProfileTypeView(); + if (context instanceof FragmentActivity) { + final Bundle options = Utils.makeSceneTransitionOption((FragmentActivity) context, + new Pair<>(profileImageView, UserFragment.TRANSITION_NAME_PROFILE_IMAGE), + new Pair<>(profileTypeView, UserFragment.TRANSITION_NAME_PROFILE_TYPE)); + Utils.openUserProfile(context, status.account_id, status.user_id, status.user_screen_name, options); + } else { + Utils.openUserProfile(context, status.account_id, status.user_id, status.user_screen_name, null); + } } public boolean isShowInReplyTo() { @@ -213,7 +261,7 @@ public abstract class AbsStatusesAdapter extends Adapter implemen @Override public final int getItemCount() { - return getStatusesCount() + (mLoadMoreIndicatorEnabled ? 1 : 0); + return getStatusesCount() + (mLoadMoreIndicatorVisible ? 1 : 0); } @Override @@ -237,37 +285,6 @@ public abstract class AbsStatusesAdapter extends Adapter implemen } } - @Override - public final void onStatusClick(StatusViewHolder holder, int position) { - if (mStatusAdapterListener != null) { - mStatusAdapterListener.onStatusClick(holder, position); - } - } - - - @Override - public void onMediaClick(StatusViewHolder holder, ParcelableMedia media, int position) { - if (mStatusAdapterListener != null) { - mStatusAdapterListener.onMediaClick(holder, media, position); - } - } - - @Override - public void onUserProfileClick(StatusViewHolder holder, int position) { - final Context context = getContext(); - final ParcelableStatus status = getStatus(position); - final View profileImageView = holder.getProfileImageView(); - final View profileTypeView = holder.getProfileTypeView(); - if (context instanceof FragmentActivity) { - final Bundle options = Utils.makeSceneTransitionOption((FragmentActivity) context, - new Pair<>(profileImageView, UserFragment.TRANSITION_NAME_PROFILE_IMAGE), - new Pair<>(profileTypeView, UserFragment.TRANSITION_NAME_PROFILE_TYPE)); - Utils.openUserProfile(context, status.account_id, status.user_id, status.user_screen_name, options); - } else { - Utils.openUserProfile(context, status.account_id, status.user_id, status.user_screen_name, null); - } - } - public void setListener(StatusAdapterListener listener) { mStatusAdapterListener = listener; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/CursorStatusesAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/CursorStatusesAdapter.java index eb30fad4e..8b7683869 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/CursorStatusesAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/CursorStatusesAdapter.java @@ -67,7 +67,7 @@ public class CursorStatusesAdapter extends AbsStatusesAdapter { @Override public ParcelableStatus getStatus(int position) { - if (hasLoadMoreIndicator() && position == getStatusesCount() - 1) return null; + if (isLoadMoreIndicatorVisible() && position == getStatusesCount() - 1) return null; final Cursor c = mCursor; if (c != null && c.moveToPosition(position)) { return new ParcelableStatus(c, mIndices); diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/MessageEntriesAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/MessageEntriesAdapter.java index fca28749b..dda8101d2 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/MessageEntriesAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/MessageEntriesAdapter.java @@ -63,7 +63,8 @@ public class MessageEntriesAdapter extends Adapter implements Consta private final int mMediaPreviewStyle; private final ReadStateManager mReadStateManager; private final OnSharedPreferenceChangeListener mReadStateChangeListener; - private boolean mLoadMoreIndicatorEnabled; + private boolean mLoadMoreSupported; + private boolean mLoadMoreIndicatorVisible; private Cursor mCursor; private MessageEntriesAdapterListener mListener; private StringLongPair[] mPositionPairs; @@ -133,10 +134,6 @@ public class MessageEntriesAdapter extends Adapter implements Consta return mTextSize; } - @Override - public boolean hasLoadMoreIndicator() { - return mLoadMoreIndicatorEnabled; - } @Override public void onReadStateChanged() { @@ -144,12 +141,32 @@ public class MessageEntriesAdapter extends Adapter implements Consta } @Override - public void setLoadMoreIndicatorEnabled(boolean enabled) { - if (mLoadMoreIndicatorEnabled == enabled) return; - mLoadMoreIndicatorEnabled = enabled; + public boolean isLoadMoreIndicatorVisible() { + return mLoadMoreIndicatorVisible; + } + + @Override + public boolean isLoadMoreSupported() { + return mLoadMoreSupported; + } + + @Override + public void setLoadMoreSupported(boolean supported) { + mLoadMoreSupported = supported; + if (!supported) { + mLoadMoreIndicatorVisible = false; + } notifyDataSetChanged(); } + @Override + public void setLoadMoreIndicatorVisible(boolean enabled) { + if (mLoadMoreIndicatorVisible == enabled) return; + mLoadMoreIndicatorVisible = enabled && mLoadMoreSupported; + notifyDataSetChanged(); + } + + @Override public boolean isGapItem(int position) { return false; @@ -228,7 +245,7 @@ public class MessageEntriesAdapter extends Adapter implements Consta @Override public final int getItemCount() { - return getMessagesCount() + (mLoadMoreIndicatorEnabled ? 1 : 0); + return getMessagesCount() + (mLoadMoreIndicatorVisible ? 1 : 0); } @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IContentCardAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IContentCardAdapter.java index 7eec1849d..807918411 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IContentCardAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IContentCardAdapter.java @@ -47,7 +47,11 @@ public interface IContentCardAdapter extends IGapSupportedAdapter, ContentCardCl float getTextSize(); - boolean hasLoadMoreIndicator(); + boolean isLoadMoreIndicatorVisible(); - void setLoadMoreIndicatorEnabled(boolean enabled); + boolean isLoadMoreSupported(); + + void setLoadMoreSupported(boolean supported); + + void setLoadMoreIndicatorVisible(boolean enabled); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AbsActivitiesFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AbsActivitiesFragment.java index bf6f17094..469b41cd9 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AbsActivitiesFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AbsActivitiesFragment.java @@ -86,7 +86,7 @@ public abstract class AbsActivitiesFragment extends BaseSupportFragment im public void onScrolled(RecyclerView recyclerView, int dx, int dy) { final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); if (isRefreshing()) return; - if (mAdapter.hasLoadMoreIndicator() && mScrollState != RecyclerView.SCROLL_STATE_IDLE + if (mAdapter.isLoadMoreIndicatorVisible() && mScrollState != RecyclerView.SCROLL_STATE_IDLE && layoutManager.findLastVisibleItemPosition() == mAdapter.getItemCount() - 1) { onLoadMoreStatuses(); } @@ -171,7 +171,7 @@ public abstract class AbsActivitiesFragment extends BaseSupportFragment im mSwipeRefreshLayout.setOnRefreshListener(this); mSwipeRefreshLayout.setColorSchemeColors(ThemeUtils.getUserAccentColor(context)); mAdapter = onCreateAdapter(context, compact); - mAdapter.setLoadMoreIndicatorEnabled(true); + mAdapter.setLoadMoreIndicatorVisible(true); mAdapter.setListener(this); final LinearLayoutManager layoutManager = new FixedLinearLayoutManager(context); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AbsStatusesFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AbsStatusesFragment.java index 46e0f47d3..828493a39 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AbsStatusesFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AbsStatusesFragment.java @@ -150,7 +150,7 @@ public abstract class AbsStatusesFragment extends BaseSupportFragment impl public void setRefreshing(boolean refreshing) { if (refreshing == mSwipeRefreshLayout.isRefreshing()) return; // if (!refreshing) updateRefreshProgressOffset(); - mSwipeRefreshLayout.setRefreshing(refreshing); + mSwipeRefreshLayout.setRefreshing(refreshing && !mAdapter.isLoadMoreIndicatorVisible()); } @Override @@ -209,6 +209,16 @@ public abstract class AbsStatusesFragment extends BaseSupportFragment impl setListShown(false); } + @Override + public void onLoadMoreContents() { + setLoadMoreIndicatorVisible(true); + setRefreshEnabled(false); + } + + public void setLoadMoreIndicatorVisible(boolean visible) { + mAdapter.setLoadMoreIndicatorVisible(visible); + } + @Override public void onStart() { super.onStart(); @@ -272,7 +282,6 @@ public abstract class AbsStatusesFragment extends BaseSupportFragment impl @Override public final void onLoadFinished(Loader loader, Data data) { - setRefreshing(false); final SharedPreferences preferences = getSharedPreferences(); final boolean rememberPosition = preferences.getBoolean(KEY_REMEMBER_POSITION, false); final boolean readFromBottom = preferences.getBoolean(KEY_READ_FROM_BOTTOM, false); @@ -300,7 +309,7 @@ public abstract class AbsStatusesFragment extends BaseSupportFragment impl } mAdapter.setData(data); if (!(loader instanceof IExtendedLoader) || ((IExtendedLoader) loader).isFromUser()) { - mAdapter.setLoadMoreIndicatorEnabled(hasMoreData(data)); + mAdapter.setLoadMoreSupported(hasMoreData(data)); int pos = -1; for (int i = 0, j = mAdapter.getItemCount(); i < j; i++) { if (lastReadId != -1 && lastReadId == mAdapter.getStatusId(i)) { @@ -316,6 +325,13 @@ public abstract class AbsStatusesFragment extends BaseSupportFragment impl ((IExtendedLoader) loader).setFromUser(false); } setListShown(true); + onLoadingFinished(); + } + + protected abstract void onLoadingFinished(); + + public void setRefreshEnabled(boolean enabled) { + mSwipeRefreshLayout.setEnabled(enabled); } @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/CursorStatusesFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/CursorStatusesFragment.java index 6d19d3a9a..1966d232f 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/CursorStatusesFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/CursorStatusesFragment.java @@ -59,6 +59,11 @@ import static org.mariotaku.twidere.util.Utils.shouldEnableFiltersForRTs; */ public abstract class CursorStatusesFragment extends AbsStatusesFragment { + @Override + protected void onLoadingFinished() { + + } + private ContentObserver mContentObserver; public abstract Uri getContentUri(); @@ -95,6 +100,10 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment public void notifyGetStatusesTaskChanged(GetStatusesTaskEvent event) { if (!event.uri.equals(getContentUri())) return; setRefreshing(event.running); + if (!event.running) { + setLoadMoreIndicatorVisible(false); + setRefreshEnabled(true); + } } @Subscribe @@ -175,6 +184,7 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment @Override public void onLoadMoreContents() { + super.onLoadMoreContents(); AsyncTaskUtils.executeTask(new AsyncTask() { @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/DirectMessagesFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/DirectMessagesFragment.java index d93360225..cd3971096 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/DirectMessagesFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/DirectMessagesFragment.java @@ -64,6 +64,7 @@ import org.mariotaku.twidere.app.TwidereApplication; import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface; import org.mariotaku.twidere.provider.TwidereDataStore.Accounts; import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages; +import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.Inbox; import org.mariotaku.twidere.provider.TwidereDataStore.Statuses; import org.mariotaku.twidere.util.AsyncTaskUtils; import org.mariotaku.twidere.util.AsyncTwitterWrapper; @@ -73,6 +74,7 @@ import org.mariotaku.twidere.util.MultiSelectManager; import org.mariotaku.twidere.util.ThemeUtils; import org.mariotaku.twidere.util.Utils; import org.mariotaku.twidere.util.content.SupportFragmentReloadCursorObserver; +import org.mariotaku.twidere.util.message.GetMessagesTaskEvent; import org.mariotaku.twidere.util.message.TaskStateChangedEvent; import java.util.Collections; @@ -152,13 +154,6 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade super.onDetach(); } - - @Subscribe - public void notifyTaskStateChanged(TaskStateChangedEvent event) { - updateRefreshState(); - } - - @Override public void onEntryClick(int position, DirectMessageEntry entry) { Utils.openMessageConversation(getActivity(), entry.account_id, entry.conversation_id); @@ -219,7 +214,9 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade if (getActivity() == null) return; mFirstVisibleItem = -1; mAdapter.setCursor(cursor); - mAdapter.setLoadMoreIndicatorEnabled(cursor != null && cursor.getCount() > 0); + mAdapter.setLoadMoreIndicatorVisible(false); + mAdapter.setLoadMoreSupported(cursor != null && cursor.getCount() > 0); + mSwipeRefreshLayout.setEnabled(true); // mAdapter.setShowAccountColor(getActivatedAccountIds(getActivity()).length > 1); setListShown(true); } @@ -274,9 +271,19 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus(); bus.register(this); mAdapter.updateReadState(); + updateRefreshState(); } + @Subscribe + public void onGetMessagesTaskChanged(GetMessagesTaskEvent event) { + if (event.uri.equals(Inbox.CONTENT_URI) && !event.running) { + setRefreshing(false); + mAdapter.setLoadMoreIndicatorVisible(false); + mSwipeRefreshLayout.setEnabled(true); + } + } + @Override public void onStop() { final Bus bus = TwidereApplication.getInstance(getActivity()).getMessageBus(); @@ -330,12 +337,13 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade } public void setRefreshing(boolean refreshing) { - if (refreshing == mSwipeRefreshLayout.isRefreshing()) return; - mSwipeRefreshLayout.setRefreshing(refreshing); + if (mAdapter == null || refreshing == mSwipeRefreshLayout.isRefreshing()) return; + mSwipeRefreshLayout.setRefreshing(refreshing && !mAdapter.isLoadMoreIndicatorVisible()); } public boolean isRefreshing() { - return mSwipeRefreshLayout.isRefreshing(); + if (mSwipeRefreshLayout == null || mAdapter == null) return false; + return mSwipeRefreshLayout.isRefreshing() || mAdapter.isLoadMoreIndicatorVisible(); } private void addReadPosition(final int firstVisibleItem) { @@ -359,6 +367,8 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade // private void loadMoreMessages() { if (isRefreshing()) return; + mAdapter.setLoadMoreIndicatorVisible(true); + mSwipeRefreshLayout.setEnabled(false); AsyncTaskUtils.executeTask(new AsyncTask() { @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/ParcelableStatusesFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/ParcelableStatusesFragment.java index f59e1ecec..4b41d1388 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/ParcelableStatusesFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/ParcelableStatusesFragment.java @@ -112,8 +112,17 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment> adapter = getAdapter(); final long[] maxIds = new long[]{adapter.getStatus(adapter.getStatusesCount() - 1).id}; getStatuses(null, maxIds, null); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/StatusFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/StatusFragment.java index 367e737a3..b09c12953 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/StatusFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/StatusFragment.java @@ -483,6 +483,9 @@ public class StatusFragment extends BaseSupportFragment private final boolean mDisplayMediaPreview; private final boolean mDisplayProfileImage; + private boolean mLoadMoreSupported; + private boolean mLoadMoreIndicatorVisible; + private ParcelableStatus mStatus; private ParcelableCredentials mStatusAccount; private List mConversation, mReplies; @@ -641,14 +644,31 @@ public class StatusFragment extends BaseSupportFragment return mTextSize; } + @Override - public boolean hasLoadMoreIndicator() { - return false; + public boolean isLoadMoreIndicatorVisible() { + return mLoadMoreIndicatorVisible; } @Override - public void setLoadMoreIndicatorEnabled(boolean enabled) { + public boolean isLoadMoreSupported() { + return mLoadMoreSupported; + } + @Override + public void setLoadMoreSupported(boolean supported) { + mLoadMoreSupported = supported; + if (!supported) { + mLoadMoreIndicatorVisible = false; + } + notifyDataSetChanged(); + } + + @Override + public void setLoadMoreIndicatorVisible(boolean enabled) { + if (mLoadMoreIndicatorVisible == enabled) return; + mLoadMoreIndicatorVisible = enabled && mLoadMoreSupported; + notifyDataSetChanged(); } public ParcelableStatus getStatus() { diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java b/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java index 041e3d419..401524bad 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java @@ -70,6 +70,7 @@ import org.mariotaku.twidere.util.content.ContentResolverUtils; import org.mariotaku.twidere.util.message.FavoriteCreatedEvent; import org.mariotaku.twidere.util.message.FavoriteDestroyedEvent; import org.mariotaku.twidere.util.message.FriendshipUpdatedEvent; +import org.mariotaku.twidere.util.message.GetMessagesTaskEvent; import org.mariotaku.twidere.util.message.GetStatusesTaskEvent; import org.mariotaku.twidere.util.message.ProfileUpdatedEvent; import org.mariotaku.twidere.util.message.StatusDestroyedEvent; @@ -1817,10 +1818,12 @@ public class AsyncTwitterWrapper extends TwitterWrapper { } // Delete all rows conflicting before new data inserted. - final Expression deleteWhere = Expression.and(Expression.equals(DirectMessages.ACCOUNT_ID, accountId), - Expression.in(new Column(DirectMessages.MESSAGE_ID), new RawItemArray(messageIds))); - final Uri deleteUri = UriUtils.appendQueryParameters(uri, QUERY_PARAM_NOTIFY, false); - mResolver.delete(deleteUri, deleteWhere.getSQL(), null); +// final Expression deleteWhere = Expression.and(Expression.equals(DirectMessages.ACCOUNT_ID, accountId), +// Expression.in(new Column(DirectMessages.MESSAGE_ID), new RawItemArray(messageIds))); +// final Uri deleteUri = UriUtils.appendQueryParameters(uri, QUERY_PARAM_NOTIFY, false); +// mResolver.delete(deleteUri, deleteWhere.getSQL(), null); + + // Insert previously fetched items. final Uri insertUri = UriUtils.appendQueryParameters(uri, QUERY_PARAM_NOTIFY, notify); @@ -1834,9 +1837,18 @@ public class AsyncTwitterWrapper extends TwitterWrapper { return since_ids != null && since_ids.length == account_ids.length; } + @Override + protected void onPreExecute() { + super.onPreExecute(); + final Bus bus = TwidereApplication.getInstance(getContext()).getMessageBus(); + bus.post(new GetMessagesTaskEvent(getDatabaseUri(), true)); + } + @Override protected void onPostExecute(final List result) { super.onPostExecute(result); + final Bus bus = TwidereApplication.getInstance(getContext()).getMessageBus(); + bus.post(new GetMessagesTaskEvent(getDatabaseUri(), false)); for (final TwitterListResponse response : result) { if (response.list == null) { mMessagesManager.showErrorMessage(R.string.action_refreshing_direct_messages, diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/ContentListScrollListener.java b/twidere/src/main/java/org/mariotaku/twidere/util/ContentListScrollListener.java index 618b04c08..c33751e4c 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/ContentListScrollListener.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/ContentListScrollListener.java @@ -54,7 +54,8 @@ public class ContentListScrollListener extends OnScrollListener { } final IContentCardAdapter adapter = mContentListSupport.getAdapter(); final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); - if (!mContentListSupport.isRefreshing() && adapter.hasLoadMoreIndicator() && mScrollState != RecyclerView.SCROLL_STATE_IDLE + if (!mContentListSupport.isRefreshing() && adapter.isLoadMoreSupported() + && !adapter.isLoadMoreIndicatorVisible() && mScrollState != RecyclerView.SCROLL_STATE_IDLE && layoutManager.findLastVisibleItemPosition() == adapter.getItemCount() - 1) { mContentListSupport.onLoadMoreContents(); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/content/TwidereSQLiteOpenHelper.java b/twidere/src/main/java/org/mariotaku/twidere/util/content/TwidereSQLiteOpenHelper.java index 872fa4556..d9d0b6334 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/content/TwidereSQLiteOpenHelper.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/content/TwidereSQLiteOpenHelper.java @@ -119,8 +119,14 @@ public final class TwidereSQLiteOpenHelper extends SQLiteOpenHelper implements C } private void createTriggers(SQLiteDatabase db) { + db.execSQL(SQLQueryBuilder.dropTrigger(true, "delete_old_statuses").getSQL()); + db.execSQL(SQLQueryBuilder.dropTrigger(true, "delete_old_mentions").getSQL()); + db.execSQL(SQLQueryBuilder.dropTrigger(true, "delete_old_received_messages").getSQL()); + db.execSQL(SQLQueryBuilder.dropTrigger(true, "delete_old_sent_messages").getSQL()); db.execSQL(createDeleteDuplicateStatusTrigger("delete_old_statuses", Statuses.TABLE_NAME).getSQL()); db.execSQL(createDeleteDuplicateStatusTrigger("delete_old_mentions", Mentions.TABLE_NAME).getSQL()); + db.execSQL(createDeleteDuplicateMessageTrigger("delete_old_received_messages", DirectMessages.Inbox.TABLE_NAME).getSQL()); + db.execSQL(createDeleteDuplicateMessageTrigger("delete_old_sent_messages", DirectMessages.Outbox.TABLE_NAME).getSQL()); } private SQLQuery createDeleteDuplicateStatusTrigger(String triggerName, String tableName) { @@ -135,6 +141,18 @@ public final class TwidereSQLiteOpenHelper extends SQLiteOpenHelper implements C } + private SQLQuery createDeleteDuplicateMessageTrigger(String triggerName, String tableName) { + final Table table = new Table(tableName); + final SQLDeleteQuery deleteOld = SQLQueryBuilder.deleteFrom(table).where(Expression.and( + Expression.equals(new Column(DirectMessages.ACCOUNT_ID), new Column(Table.NEW, DirectMessages.ACCOUNT_ID)), + Expression.equals(new Column(DirectMessages.MESSAGE_ID), new Column(Table.NEW, DirectMessages.MESSAGE_ID)) + )).build(); + return SQLQueryBuilder.createTrigger(false, true, triggerName) + .type(Type.BEFORE).event(Event.INSERT).on(table).forEachRow(true) + .actions(deleteOld).build(); + } + + @Override public void onDowngrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { handleVersionChange(db, oldVersion, newVersion); diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/message/GetMessagesTaskEvent.java b/twidere/src/main/java/org/mariotaku/twidere/util/message/GetMessagesTaskEvent.java new file mode 100644 index 000000000..4f800e571 --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/util/message/GetMessagesTaskEvent.java @@ -0,0 +1,38 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2015 Mariotaku Lee + * + * 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 . + */ + +package org.mariotaku.twidere.util.message; + +import android.net.Uri; +import android.support.annotation.NonNull; + +/** + * Created by mariotaku on 14/12/10. + */ +public class GetMessagesTaskEvent { + + @NonNull + public final Uri uri; + public final boolean running; + + public GetMessagesTaskEvent(@NonNull Uri uri, boolean running) { + this.uri = uri; + this.running = running; + } +} diff --git a/twidere/src/main/res/values/colors.xml b/twidere/src/main/res/values/colors.xml index 34631c6e4..ac2d07990 100644 --- a/twidere/src/main/res/values/colors.xml +++ b/twidere/src/main/res/values/colors.xml @@ -2,8 +2,8 @@ #003366 - #e5e5e5 - #101010 + #e3e3e3 + #101010 #f5f5f5 #333333 #ff000000 @@ -27,5 +27,7 @@ @color/material_cyan #40808080 #a0000000 + #1a1a1a + #fafafa \ No newline at end of file diff --git a/twidere/src/main/res/values/themes.xml b/twidere/src/main/res/values/themes.xml index 8e02bce29..b26002273 100644 --- a/twidere/src/main/res/values/themes.xml +++ b/twidere/src/main/res/values/themes.xml @@ -30,7 +30,7 @@ - + @color/background_color_window_dark @android:style/Widget.DeviceDefault.ActionBar.Solid @@ -42,7 +42,7 @@ @style/Widget.CardActionButton @style/Widget.ProfileImage @style/Widget.ProfileImage.Large - #1a1a1a + @color/background_color_card_item_dark @color/action_icon_light @@ -57,7 +57,7 @@ - + @color/background_color_window_light @@ -157,7 +157,7 @@ @style/Widget.CardActionButton @style/Widget.ProfileImage @style/Widget.ProfileImage.Large - #1a1a1a + @color/background_color_card_item_dark @@ -174,7 +174,7 @@ @style/Widget.Light.CardActionButton @style/Widget.Light.ProfileImage @style/Widget.Light.ProfileImage.Large - #f8f8f8 + @color/background_color_card_item_light @@ -239,7 +239,7 @@ @style/Widget.CardActionButton @style/Widget.ProfileImage @style/Widget.ProfileImage.Large - #1a1a1a + @color/background_color_card_item_dark @color/action_icon_light @@ -297,11 +297,11 @@