diff options
author | Dan Roundhill <dan@automattic.com> | 2015-02-24 14:46:54 -0800 |
---|---|---|
committer | Dan Roundhill <dan@automattic.com> | 2015-02-24 14:46:54 -0800 |
commit | f3b456fc648da95eff62172f162aeac3d7d2b0f3 (patch) | |
tree | 77b3e2c3fa5054663baab24fcd54e6c5e4899706 /WordPress/src/main/java/org/wordpress | |
parent | 3f1e5c7b6f2abc1c1606ed2cd60cd47acda882c1 (diff) | |
parent | 99b3ffac1b8d328e6f52a001a7ae7e614a227835 (diff) | |
download | gradle-perf-android-medium-f3b456fc648da95eff62172f162aeac3d7d2b0f3.tar.gz |
Merge branch 'develop' into issue/2298-2fa-improvements
Conflicts:
WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListActivity.java
Diffstat (limited to 'WordPress/src/main/java/org/wordpress')
8 files changed, 282 insertions, 356 deletions
diff --git a/WordPress/src/main/java/org/wordpress/android/datasets/ReaderPostTable.java b/WordPress/src/main/java/org/wordpress/android/datasets/ReaderPostTable.java index 2e0860ed5..0a1231c81 100644 --- a/WordPress/src/main/java/org/wordpress/android/datasets/ReaderPostTable.java +++ b/WordPress/src/main/java/org/wordpress/android/datasets/ReaderPostTable.java @@ -576,9 +576,9 @@ public class ReaderPostTable { if (tag.tagType == ReaderTagType.DEFAULT) { // skip posts that are no longer liked if this is "Posts I Like", skip posts that are no // longer followed if this is "Blogs I Follow" - if (tag.getTagName().equals(ReaderTag.TAG_NAME_LIKED)) { + if (tag.isPostsILike()) { sql += " AND tbl_posts.is_liked != 0"; - } else if (tag.getTagName().equals(ReaderTag.TAG_NAME_FOLLOWING)) { + } else if (tag.isBlogsIFollow()) { sql += " AND tbl_posts.is_followed != 0"; } } @@ -630,9 +630,9 @@ public class ReaderPostTable { + " AND tbl_post_tags.tag_type=?"; if (tag.tagType == ReaderTagType.DEFAULT) { - if (tag.getTagName().equals(ReaderTag.TAG_NAME_LIKED)) { + if (tag.isPostsILike()) { sql += " AND tbl_posts.is_liked != 0"; - } else if (tag.getTagName().equals(ReaderTag.TAG_NAME_FOLLOWING)) { + } else if (tag.isBlogsIFollow()) { sql += " AND tbl_posts.is_followed != 0"; } } diff --git a/WordPress/src/main/java/org/wordpress/android/models/ReaderTag.java b/WordPress/src/main/java/org/wordpress/android/models/ReaderTag.java index 5e1697f32..5c86bbaca 100644 --- a/WordPress/src/main/java/org/wordpress/android/models/ReaderTag.java +++ b/WordPress/src/main/java/org/wordpress/android/models/ReaderTag.java @@ -6,21 +6,17 @@ import org.wordpress.android.ui.reader.utils.ReaderUtils; import org.wordpress.android.util.StringUtils; import java.io.Serializable; -import java.lang.Character; import java.util.regex.Pattern; public class ReaderTag implements Serializable { private String tagName; private String endpoint; - public ReaderTagType tagType; - - public static final String TAG_ID_FOLLOWING = "following"; - public static final String TAG_ID_LIKED = "liked"; + public final ReaderTagType tagType; // these are the default tag names, which aren't localized in the /read/menu/ response - public static final String TAG_NAME_LIKED = "Posts I Like"; public static final String TAG_NAME_FOLLOWING = "Blogs I Follow"; - public static final String TAG_NAME_FRESHLY_PRESSED = "Freshly Pressed"; + private static final String TAG_NAME_LIKED = "Posts I Like"; + private static final String TAG_NAME_FRESHLY_PRESSED = "Freshly Pressed"; private static final String TAG_NAME_DEFAULT = TAG_NAME_FRESHLY_PRESSED; public ReaderTag(String tagName, String endpoint, ReaderTagType tagType) { @@ -45,30 +41,14 @@ public class ReaderTag implements Serializable { public String getEndpoint() { return StringUtils.notNullStr(endpoint); } - public void setEndpoint(String endpoint) { + void setEndpoint(String endpoint) { this.endpoint = StringUtils.notNullStr(endpoint); } - /** - * Extract tag Id from endpoint, only works for ReaderTagType.DEFAULT - * - * @return a string Id if tagType is ReaderTagType.DEFAULT, empty string else - */ - public String getStringIdFromEndpoint() { - if (tagType != ReaderTagType.DEFAULT) { - return ""; - } - String[] splitted = endpoint.split("/"); - if (splitted != null && splitted.length > 0) { - return splitted[splitted.length - 1]; - } - return ""; - } - public String getTagName() { return StringUtils.notNullStr(tagName); } - public void setTagName(String name) { + void setTagName(String name) { this.tagName = StringUtils.notNullStr(name); } public String getCapitalizedTagName() { @@ -114,11 +94,8 @@ public class ReaderTag implements Serializable { */ private static final Pattern INVALID_CHARS = Pattern.compile("^.*[~#@*+%{}<>\\[\\]|\"\\_].*$"); public static boolean isValidTagName(String tagName) { - if (TextUtils.isEmpty(tagName)) - return false; - if (INVALID_CHARS.matcher(tagName).matches()) - return false; - return true; + return !TextUtils.isEmpty(tagName) + && !INVALID_CHARS.matcher(tagName).matches(); } /* @@ -164,9 +141,17 @@ public class ReaderTag implements Serializable { if (tag1 == null || tag2 == null) { return false; } - if (tag1.tagType != tag2.tagType) { - return false; - } - return (tag1.getSanitizedTagName().equalsIgnoreCase(tag2.getSanitizedTagName())); + return tag1.tagType == tag2.tagType + && tag1.getSanitizedTagName().equalsIgnoreCase(tag2.getSanitizedTagName()); + } + + public boolean isPostsILike() { + return getTagName().equals(TAG_NAME_LIKED); + } + public boolean isBlogsIFollow() { + return getTagName().equals(TAG_NAME_FOLLOWING); + } + public boolean isFreshlyPressed() { + return getTagName().equals(TAG_NAME_FRESHLY_PRESSED); } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderEvents.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderEvents.java index f3c05e7b8..0c14d4018 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderEvents.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderEvents.java @@ -1,5 +1,9 @@ package org.wordpress.android.ui.reader; +import org.wordpress.android.util.DateTimeUtils; + +import java.util.Date; + /** * Reader-related EventBus event classes */ @@ -9,4 +13,17 @@ public class ReaderEvents { public static class FollowedBlogsChanged {} public static class RecommendedBlogsChanged {} + + public static class HasPurgedDatabase {} + public static class HasPerformedInitialUpdate {} + + public static class UpdatedFollowedTagsAndBlogs { + private Date mUpdateDate; + public UpdatedFollowedTagsAndBlogs() { + mUpdateDate = new Date(); + } + public int minutesSinceLastUpdate() { + return DateTimeUtils.minutesBetween(mUpdateDate, new Date()); + } + } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.java index c75480bd1..de006acc6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.java @@ -207,7 +207,7 @@ public class ReaderPostDetailFragment extends Fragment public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); menu.clear(); - inflater.inflate(R.menu.reader_native_detail, menu); + inflater.inflate(R.menu.reader_detail, menu); } @Override diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListActivity.java index d54895840..fa3bc395a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListActivity.java @@ -4,69 +4,33 @@ import android.app.Activity; import android.app.Fragment; import android.content.Intent; import android.os.Bundle; -import android.view.MenuItem; import android.view.View; import org.wordpress.android.R; import org.wordpress.android.analytics.AnalyticsTracker; -import org.wordpress.android.datasets.ReaderDatabase; -import org.wordpress.android.datasets.ReaderPostTable; import org.wordpress.android.datasets.ReaderTagTable; import org.wordpress.android.models.ReaderTag; -import org.wordpress.android.models.ReaderTagType; import org.wordpress.android.ui.WPDrawerActivity; import org.wordpress.android.ui.accounts.SignInActivity; import org.wordpress.android.ui.prefs.AppPrefs; -import org.wordpress.android.ui.reader.ReaderInterfaces.OnPostSelectedListener; -import org.wordpress.android.ui.reader.ReaderInterfaces.OnTagSelectedListener; -import org.wordpress.android.ui.reader.actions.ReaderUserActions; -import org.wordpress.android.ui.reader.services.ReaderUpdateService; -import org.wordpress.android.ui.reader.services.ReaderUpdateService.UpdateTask; import org.wordpress.android.util.AppLog; import org.wordpress.android.util.AppLog.T; -import org.wordpress.android.util.NetworkUtils; - -import java.util.EnumSet; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; import javax.annotation.Nonnull; +import de.greenrobot.event.EventBus; + /* * this activity serves as the host for ReaderPostListFragment */ -public class ReaderPostListActivity extends WPDrawerActivity - implements OnPostSelectedListener, - OnTagSelectedListener { - - private static boolean mHasPerformedInitialUpdate; - private static boolean mHasPerformedPurge; - - private final ScheduledExecutorService mUpdateScheduler = Executors.newScheduledThreadPool(1); - - private ReaderTypes.ReaderPostListType mPostListType; +public class ReaderPostListActivity extends WPDrawerActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); createMenuDrawer(R.layout.reader_activity_post_list); readIntent(getIntent(), savedInstanceState); - - // start updating tags & blogs after 500ms, then update them hourly - mUpdateScheduler.scheduleWithFixedDelay( - new Runnable() { - public void run() { - updateFollowedTagsAndBlogs(); - } - }, 500, (1000 * 60) * 60, TimeUnit.MILLISECONDS); - } - - @Override - protected void onDestroy() { - mUpdateScheduler.shutdownNow(); - super.onDestroy(); } private void readIntent(Intent intent, Bundle savedInstanceState) { @@ -74,14 +38,15 @@ public class ReaderPostListActivity extends WPDrawerActivity return; } + ReaderTypes.ReaderPostListType postListType; if (intent.hasExtra(ReaderConstants.ARG_POST_LIST_TYPE)) { - mPostListType = (ReaderTypes.ReaderPostListType) intent.getSerializableExtra(ReaderConstants.ARG_POST_LIST_TYPE); + postListType = (ReaderTypes.ReaderPostListType) intent.getSerializableExtra(ReaderConstants.ARG_POST_LIST_TYPE); } else { - mPostListType = ReaderTypes.DEFAULT_POST_LIST_TYPE; + postListType = ReaderTypes.DEFAULT_POST_LIST_TYPE; } // hide drawer toggle and enable back arrow click if this is blog preview or tag preview - if (mPostListType.isPreviewType() && getDrawerToggle() != null) { + if (postListType.isPreviewType() && getDrawerToggle() != null) { getDrawerToggle().setDrawerIndicatorEnabled(false); getToolbar().setNavigationOnClickListener(new View.OnClickListener() { @Override @@ -94,7 +59,7 @@ public class ReaderPostListActivity extends WPDrawerActivity if (savedInstanceState == null) { AnalyticsTracker.track(AnalyticsTracker.Stat.READER_ACCESSED); - if (mPostListType == ReaderTypes.ReaderPostListType.BLOG_PREVIEW) { + if (postListType == ReaderTypes.ReaderPostListType.BLOG_PREVIEW) { long blogId = intent.getLongExtra(ReaderConstants.ARG_BLOG_ID, 0); long feedId = intent.getLongExtra(ReaderConstants.ARG_FEED_ID, 0); if (feedId != 0) { @@ -111,15 +76,15 @@ public class ReaderPostListActivity extends WPDrawerActivity tag = AppPrefs.getReaderTag(); } // if this is a followed tag and it doesn't exist, revert to default tag - if (mPostListType == ReaderTypes.ReaderPostListType.TAG_FOLLOWED && !ReaderTagTable.tagExists(tag)) { + if (postListType == ReaderTypes.ReaderPostListType.TAG_FOLLOWED && !ReaderTagTable.tagExists(tag)) { tag = ReaderTag.getDefaultTag(); } - showListFragmentForTag(tag, mPostListType); + showListFragmentForTag(tag, postListType); } } - switch (mPostListType) { + switch (postListType) { case TAG_PREVIEW: setTitle(R.string.reader_title_tag_preview); break; @@ -131,27 +96,12 @@ public class ReaderPostListActivity extends WPDrawerActivity } // hide the static drawer for blog/tag preview - if (isStaticMenuDrawer() && mPostListType.isPreviewType()) { + if (isStaticMenuDrawer() && postListType.isPreviewType()) { hideDrawer(); } } @Override - protected void onStart() { - super.onStart(); - - // purge the database of older data at startup, but only if there's an active connection - // since we don't want to purge posts that the user would expect to see when offline - if (!mHasPerformedPurge && NetworkUtils.isNetworkAvailable(this)) { - mHasPerformedPurge = true; - ReaderDatabase.purgeAsync(); - } - if (!mHasPerformedInitialUpdate) { - performInitialUpdate(); - } - } - - @Override public void onSaveInstanceState(@Nonnull Bundle outState) { if (outState.isEmpty()) { outState.putBoolean("bug_19917_fix", true); @@ -169,60 +119,25 @@ public class ReaderPostListActivity extends WPDrawerActivity } @Override - public boolean onOptionsItemSelected(final MenuItem item) { - switch (item.getItemId()) { - case R.id.menu_tags: - ReaderActivityLauncher.showReaderSubsForResult(this); - return true; - default: - return super.onOptionsItemSelected(item); - } - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - boolean isResultOK = (resultCode == Activity.RESULT_OK); - final ReaderPostListFragment listFragment = getListFragment(); - switch (requestCode) { - // user just returned from the tags/subs activity - case ReaderConstants.INTENT_READER_SUBS : - if (data != null && listFragment != null) { - boolean tagsChanged = data.getBooleanExtra(ReaderSubsActivity.KEY_TAGS_CHANGED, false); - boolean blogsChanged = data.getBooleanExtra(ReaderSubsActivity.KEY_BLOGS_CHANGED, false); - // reload tags if they were changed, and set the last tag added as the current one - if (tagsChanged) { - String lastAddedTag = data.getStringExtra(ReaderSubsActivity.KEY_LAST_ADDED_TAG_NAME); - listFragment.doTagsChanged(lastAddedTag); - } - // refresh posts if blogs changed and user is viewing "Blogs I Follow" - if (blogsChanged - && listFragment.getPostListType() == ReaderTypes.ReaderPostListType.TAG_FOLLOWED - && ReaderTag.TAG_NAME_FOLLOWING.equals(listFragment.getCurrentTagName())) { - listFragment.refreshPosts(); - } - } - break; - - // user just returned from reblogging activity, reload the displayed post if reblogging - // succeeded - case ReaderConstants.INTENT_READER_REBLOG: - if (isResultOK && data != null && listFragment != null) { - long blogId = data.getLongExtra(ReaderConstants.ARG_BLOG_ID, 0); - long postId = data.getLongExtra(ReaderConstants.ARG_POST_ID, 0); - listFragment.reloadPost(ReaderPostTable.getPost(blogId, postId, true)); - } - break; - // user just returned from the login dialog, need to perform initial update again // since creds have changed case SignInActivity.REQUEST_CODE: - if (isResultOK) { + if (resultCode == Activity.RESULT_OK) { removeListFragment(); - mHasPerformedInitialUpdate = false; - performInitialUpdate(); + EventBus.getDefault().removeStickyEvent(ReaderEvents.HasPerformedInitialUpdate.class); + } + break; + + // pass reader-related results to the fragment + case ReaderConstants.INTENT_READER_SUBS: + case ReaderConstants.INTENT_READER_REBLOG: + ReaderPostListFragment listFragment = getListFragment(); + if (listFragment != null) { + listFragment.onActivityResult(requestCode, resultCode, data); } break; } @@ -233,7 +148,7 @@ public class ReaderPostListActivity extends WPDrawerActivity super.onSignout(); AppLog.i(T.READER, "reader post list > user signed out"); - mHasPerformedInitialUpdate = false; + EventBus.getDefault().removeStickyEvent(ReaderEvents.HasPerformedInitialUpdate.class); // reader database will have been cleared by the time this is called, but the fragment must // be removed or else it will continue to show the same articles - onResume() will take @@ -241,10 +156,6 @@ public class ReaderPostListActivity extends WPDrawerActivity removeListFragment(); } - ReaderTypes.ReaderPostListType getPostListType() { - return (mPostListType != null ? mPostListType : ReaderTypes.DEFAULT_POST_LIST_TYPE); - } - private void removeListFragment() { Fragment listFragment = getListFragment(); if (listFragment != null) { @@ -301,85 +212,4 @@ public class ReaderPostListActivity extends WPDrawerActivity } return ((ReaderPostListFragment) fragment); } - - private boolean hasListFragment() { - return (getListFragment() != null); - } - - /* - * initial update performed the first time the user opens the reader - */ - private void performInitialUpdate() { - if (!NetworkUtils.isNetworkAvailable(this)) { - return; - } - - mHasPerformedInitialUpdate = true; - - // update current user to ensure we have their user_id as well as their latest info - // in case they changed their avatar, name, etc. since last time - AppLog.d(T.READER, "reader post list > updating current user"); - ReaderUserActions.updateCurrentUser(null); - } - - /* - * start background service to get the latest followed tags and blogs - */ - void updateFollowedTagsAndBlogs() { - AppLog.d(T.READER, "reader post list > updating tags and blogs"); - ReaderUpdateService.startService(this, - EnumSet.of(UpdateTask.TAGS, UpdateTask.FOLLOWED_BLOGS)); - } - - /* - * user tapped a post in the list fragment - */ - @Override - public void onPostSelected(long blogId, long postId) { - // skip if this activity no longer has the focus - this prevents the post detail from - // being shown multiple times if the user quickly taps a post more than once - if (!this.hasWindowFocus()) { - AppLog.w(T.READER, "reader post list > post selected when activity not focused"); - return; - } - - AnalyticsTracker.track(AnalyticsTracker.Stat.READER_OPENED_ARTICLE); - - ReaderPostListFragment listFragment = getListFragment(); - if (listFragment != null) { - switch (getPostListType()) { - case TAG_FOLLOWED: - case TAG_PREVIEW: - ReaderActivityLauncher.showReaderPostPagerForTag( - this, - listFragment.getCurrentTag(), - getPostListType(), - blogId, - postId); - break; - case BLOG_PREVIEW: - ReaderActivityLauncher.showReaderPostPagerForBlog( - this, - blogId, - postId); - break; - } - } - } - - /* - * user tapped a tag in the list fragment - */ - @Override - public void onTagSelected(String tagName) { - ReaderTag tag = new ReaderTag(tagName, ReaderTagType.FOLLOWED); - if (hasListFragment() && getListFragment().getPostListType().equals(ReaderTypes.ReaderPostListType.TAG_PREVIEW)) { - // user is already previewing a tag, so change current tag in existing preview - getListFragment().setCurrentTag(tag); - } else { - // user isn't previewing a tag, so open in tag preview - ReaderActivityLauncher.showReaderTagPreview(this, tag); - } - } - } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java index 7efd9a735..b2af894d3 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java @@ -5,6 +5,7 @@ import android.annotation.SuppressLint; import android.app.Activity; import android.app.Fragment; import android.content.Context; +import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.os.Handler; @@ -39,6 +40,7 @@ import com.cocosw.undobar.UndoBarController; import org.wordpress.android.R; import org.wordpress.android.analytics.AnalyticsTracker; import org.wordpress.android.datasets.ReaderBlogTable; +import org.wordpress.android.datasets.ReaderDatabase; import org.wordpress.android.datasets.ReaderPostTable; import org.wordpress.android.datasets.ReaderTagTable; import org.wordpress.android.models.ReaderBlog; @@ -47,14 +49,15 @@ import org.wordpress.android.models.ReaderTag; import org.wordpress.android.models.ReaderTagType; import org.wordpress.android.ui.prefs.AppPrefs; import org.wordpress.android.ui.reader.ReaderTypes.ReaderPostListType; -import org.wordpress.android.ui.reader.ReaderTypes.RefreshType; import org.wordpress.android.ui.reader.actions.ReaderActions; import org.wordpress.android.ui.reader.actions.ReaderActions.RequestDataAction; import org.wordpress.android.ui.reader.actions.ReaderBlogActions; import org.wordpress.android.ui.reader.actions.ReaderPostActions; import org.wordpress.android.ui.reader.actions.ReaderTagActions; +import org.wordpress.android.ui.reader.actions.ReaderUserActions; import org.wordpress.android.ui.reader.adapters.ReaderPostAdapter; import org.wordpress.android.ui.reader.adapters.ReaderTagSpinnerAdapter; +import org.wordpress.android.ui.reader.services.ReaderUpdateService; import org.wordpress.android.ui.reader.views.ReaderBlogInfoView; import org.wordpress.android.ui.reader.views.ReaderFollowButton; import org.wordpress.android.ui.reader.views.ReaderRecyclerView; @@ -70,13 +73,17 @@ import org.wordpress.android.util.ptr.SwipeToRefreshHelper; import org.wordpress.android.util.ptr.SwipeToRefreshHelper.RefreshListener; import java.util.ArrayList; +import java.util.EnumSet; import java.util.HashMap; import java.util.Map; import java.util.Stack; import de.greenrobot.event.EventBus; -public class ReaderPostListFragment extends Fragment { +public class ReaderPostListFragment extends Fragment + implements ReaderInterfaces.OnPostSelectedListener, + ReaderInterfaces.OnTagSelectedListener, + ReaderInterfaces.OnPostPopupListener { private Spinner mSpinner; private ReaderTagSpinnerAdapter mSpinnerAdapter; @@ -84,9 +91,6 @@ public class ReaderPostListFragment extends Fragment { private ReaderPostAdapter mPostAdapter; private ReaderRecyclerView mRecyclerView; - private ReaderInterfaces.OnPostSelectedListener mPostSelectedListener; - private ReaderInterfaces.OnTagSelectedListener mOnTagSelectedListener; - private SwipeToRefreshHelper mSwipeToRefreshHelper; private View mNewPostsBar; private View mEmptyView; @@ -249,7 +253,7 @@ public class ReaderPostListFragment extends Fragment { && getPostListType() == ReaderPostListType.TAG_FOLLOWED && ReaderTagTable.shouldAutoUpdateTag(mCurrentTag)) { AppLog.i(T.READER, "reader post list > auto-updating current tag after resume"); - updatePostsWithTag(getCurrentTag(), RequestDataAction.LOAD_NEWER, RefreshType.AUTOMATIC); + updatePostsWithTag(getCurrentTag(), RequestDataAction.LOAD_NEWER); } } } @@ -257,7 +261,14 @@ public class ReaderPostListFragment extends Fragment { @Override public void onStart() { super.onStart(); + EventBus.getDefault().register(this); + + purgeDatabaseIfNeeded(); + performInitialUpdateIfNeeded(); + if (getPostListType() == ReaderPostListType.TAG_FOLLOWED) { + updateFollowedTagsAndBlogsIfNeeded(); + } } @Override @@ -283,7 +294,8 @@ public class ReaderPostListFragment extends Fragment { public void onEventMainThread(ReaderEvents.FollowedBlogsChanged event) { // refresh posts if user is viewing "Blogs I Follow" if (getPostListType() == ReaderTypes.ReaderPostListType.TAG_FOLLOWED - && ReaderTag.TAG_NAME_FOLLOWING.equals(getCurrentTagName())) { + && hasCurrentTag() + && getCurrentTag().isBlogsIFollow()) { refreshPosts(); } } @@ -378,7 +390,7 @@ public class ReaderPostListFragment extends Fragment { switch (getPostListType()) { case TAG_FOLLOWED: case TAG_PREVIEW: - updatePostsWithTag(getCurrentTag(), RequestDataAction.LOAD_NEWER, RefreshType.MANUAL); + updatePostsWithTag(getCurrentTag(), RequestDataAction.LOAD_NEWER); break; case BLOG_PREVIEW: updatePostsInCurrentBlogOrFeed(RequestDataAction.LOAD_NEWER); @@ -393,18 +405,6 @@ public class ReaderPostListFragment extends Fragment { return rootView; } - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - - if (activity instanceof ReaderInterfaces.OnPostSelectedListener) { - mPostSelectedListener = (ReaderInterfaces.OnPostSelectedListener) activity; - } - if (activity instanceof ReaderInterfaces.OnTagSelectedListener) { - mOnTagSelectedListener = (ReaderInterfaces.OnTagSelectedListener) activity; - } - } - /* * animate in the blog/tag info header after a brief delay */ @@ -467,7 +467,7 @@ public class ReaderPostListFragment extends Fragment { boolean isRecreated = (savedInstanceState != null); getPostAdapter().setCurrentTag(mCurrentTag); if (!isRecreated && ReaderTagTable.shouldAutoUpdateTag(mCurrentTag)) { - updatePostsWithTag(getCurrentTag(), RequestDataAction.LOAD_NEWER, RefreshType.AUTOMATIC); + updatePostsWithTag(getCurrentTag(), RequestDataAction.LOAD_NEWER); } } @@ -485,9 +485,6 @@ public class ReaderPostListFragment extends Fragment { animateHeaderDelayed(); break; } - - getPostAdapter().setOnTagSelectedListener(mOnTagSelectedListener); - getPostAdapter().setOnPostPopupListener(mOnPostPopupListener); } /* @@ -556,41 +553,29 @@ public class ReaderPostListFragment extends Fragment { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); + // only followed tag list has a menu if (getPostListType() == ReaderPostListType.TAG_FOLLOWED) { - inflater.inflate(R.menu.reader_native, menu); + inflater.inflate(R.menu.reader_list, menu); setupActionBar(); } } - /* - * called when user taps dropdown arrow icon next to a post - shows a popup menu - * that enables blocking the blog the post is in - */ - private final ReaderInterfaces.OnPostPopupListener mOnPostPopupListener = new ReaderInterfaces.OnPostPopupListener() { - @Override - public void onShowPostPopup(View view, final ReaderPost post) { - if (view == null || post == null) { - return; - } - - PopupMenu popup = new PopupMenu(getActivity(), view); - MenuItem menuItem = popup.getMenu().add(getString(R.string.reader_menu_block_blog)); - menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - blockBlogForPost(post); - return true; - } - }); - popup.show(); + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.menu_tags: + ReaderActivityLauncher.showReaderSubsForResult(getActivity()); + return true; + default: + return super.onOptionsItemSelected(item); } - }; + } /* - * blocks the blog associated with the passed post and removes all posts in that blog - * from the adapter - */ + * blocks the blog associated with the passed post and removes all posts in that blog + * from the adapter + */ private void blockBlogForPost(final ReaderPost post) { if (post == null || !hasPostAdapter()) { return; @@ -688,11 +673,11 @@ public class ReaderPostListFragment extends Fragment { Map<String, String> properties = new HashMap<>(); properties.put("tag", tag.getTagName()); AnalyticsTracker.track(AnalyticsTracker.Stat.READER_LOADED_TAG, properties); - if (tag.getTagName().equals(ReaderTag.TAG_NAME_FRESHLY_PRESSED)) { + if (tag.isFreshlyPressed()) { AnalyticsTracker.track(AnalyticsTracker.Stat.READER_LOADED_FRESHLY_PRESSED); } } - setCurrentTag(tag); + setCurrentTag(tag, true); AppLog.d(T.READER, String.format("reader post list > tag %s displayed", tag.getTagNameForLog())); } @@ -739,26 +724,14 @@ public class ReaderPostListFragment extends Fragment { titleResId = R.string.reader_empty_posts_in_tag_updating; } else if (getPostListType() == ReaderPostListType.BLOG_PREVIEW) { titleResId = R.string.reader_empty_posts_in_blog; - } else if (getPostListType() == ReaderPostListType.TAG_FOLLOWED && getSpinnerAdapter() != null) { - int tagIndex = getSpinnerAdapter().getIndexOfTag(mCurrentTag); - String tagId; - if (tagIndex > -1) { - ReaderTag tag = (ReaderTag) getSpinnerAdapter().getItem(tagIndex); - tagId = tag.getStringIdFromEndpoint(); + } else if (getPostListType() == ReaderPostListType.TAG_FOLLOWED && hasCurrentTag()) { + if (getCurrentTag().isBlogsIFollow()) { + titleResId = R.string.reader_empty_followed_blogs_title; + descriptionResId = R.string.reader_empty_followed_blogs_description; + } else if (getCurrentTag().isPostsILike()) { + titleResId = R.string.reader_empty_posts_liked; } else { - tagId = ""; - } - switch (tagId) { - case ReaderTag.TAG_ID_FOLLOWING: - titleResId = R.string.reader_empty_followed_blogs_title; - descriptionResId = R.string.reader_empty_followed_blogs_description; - break; - case ReaderTag.TAG_ID_LIKED: - titleResId = R.string.reader_empty_posts_liked; - break; - default: - titleResId = R.string.reader_empty_posts_in_tag; - break; + titleResId = R.string.reader_empty_posts_in_tag; } } else { titleResId = R.string.reader_empty_posts_in_tag; @@ -818,7 +791,7 @@ public class ReaderPostListFragment extends Fragment { case TAG_PREVIEW: if (ReaderPostTable.getNumPostsWithTag(mCurrentTag) < ReaderConstants.READER_MAX_POSTS_TO_DISPLAY) { // request older posts - updatePostsWithTag(getCurrentTag(), RequestDataAction.LOAD_OLDER, RefreshType.MANUAL); + updatePostsWithTag(getCurrentTag(), RequestDataAction.LOAD_OLDER); AnalyticsTracker.track(AnalyticsTracker.Stat.READER_INFINITE_SCROLL); } break; @@ -856,7 +829,9 @@ public class ReaderPostListFragment extends Fragment { AppLog.d(T.READER, "reader post list > creating post adapter"); Context context = WPActivityUtils.getThemedContext(getActivity()); mPostAdapter = new ReaderPostAdapter(context, getPostListType()); - mPostAdapter.setOnPostSelectedListener(mPostSelectedListener); + mPostAdapter.setOnPostSelectedListener(this); + mPostAdapter.setOnTagSelectedListener(this); + mPostAdapter.setOnPostPopupListener(this); mPostAdapter.setOnDataLoadedListener(mDataLoadedListener); mPostAdapter.setOnDataRequestedListener(mDataRequestedListener); mPostAdapter.setOnReblogRequestedListener(mRequestReblogListener); @@ -887,22 +862,10 @@ public class ReaderPostListFragment extends Fragment { return (mCurrentTag != null ? mCurrentTag.getTagName() : ""); } - private boolean hasCurrentTag() { + boolean hasCurrentTag() { return mCurrentTag != null; } - void setCurrentTagName(String tagName) { - setCurrentTagName(tagName, true); - } - void setCurrentTagName(String tagName, boolean allowAutoUpdate) { - if (TextUtils.isEmpty(tagName)) { - return; - } - setCurrentTag(new ReaderTag(tagName, ReaderTagType.FOLLOWED), allowAutoUpdate); - } - void setCurrentTag(final ReaderTag tag) { - setCurrentTag(tag, true); - } void setCurrentTag(final ReaderTag tag, boolean allowAutoUpdate) { if (tag == null) { return; @@ -941,7 +904,7 @@ public class ReaderPostListFragment extends Fragment { // update posts in this tag if it's time to do so if (allowAutoUpdate && ReaderTagTable.shouldAutoUpdateTag(tag)) { - updatePostsWithTag(tag, RequestDataAction.LOAD_NEWER, RefreshType.AUTOMATIC); + updatePostsWithTag(tag, RequestDataAction.LOAD_NEWER); } } @@ -955,15 +918,15 @@ public class ReaderPostListFragment extends Fragment { return false; } - String tag = mTagPreviewHistory.pop(); - if (isCurrentTagName(tag)) { + String tagName = mTagPreviewHistory.pop(); + if (isCurrentTagName(tagName)) { if (mTagPreviewHistory.empty()) { return false; } - tag = mTagPreviewHistory.pop(); + tagName = mTagPreviewHistory.pop(); } - setCurrentTagName(tag, false); + setCurrentTag(new ReaderTag(tagName, ReaderTagType.FOLLOWED), false); updateFollowButton(); return true; @@ -1038,15 +1001,14 @@ public class ReaderPostListFragment extends Fragment { } void updateCurrentTag() { - updatePostsWithTag(getCurrentTag(), RequestDataAction.LOAD_NEWER, RefreshType.AUTOMATIC); + updatePostsWithTag(getCurrentTag(), RequestDataAction.LOAD_NEWER); } /* * get latest posts for this tag from the server */ void updatePostsWithTag(final ReaderTag tag, - final RequestDataAction updateAction, - final RefreshType refreshType) { + final RequestDataAction updateAction) { if (tag == null) { return; } @@ -1069,13 +1031,6 @@ public class ReaderPostListFragment extends Fragment { return; } - // if this is "Posts I Like" or "Blogs I Follow" and it's a manual refresh (user tapped refresh icon), - // refresh the posts so posts that were unliked/unfollowed no longer appear - if (refreshType == RefreshType.MANUAL && isCurrentTag(tag)) { - if (tag.getTagName().equals(ReaderTag.TAG_NAME_LIKED) || tag.getTagName().equals(ReaderTag.TAG_NAME_FOLLOWING)) - refreshPosts(); - } - ReaderActions.UpdateResultListener resultListener = new ReaderActions.UpdateResultListener() { @Override public void onUpdateResult(ReaderActions.UpdateResult result) { @@ -1102,6 +1057,12 @@ public class ReaderPostListFragment extends Fragment { } else { boolean requestFailed = (result == ReaderActions.UpdateResult.FAILED); setEmptyTitleAndDescription(requestFailed); + // refresh if this is "Posts I Like" or "Blogs I Follow" so posts that + // were unliked/unfollowed no longer appear + if (updateAction == RequestDataAction.LOAD_NEWER + && (tag.isPostsILike() || tag.isBlogsIFollow())) { + refreshPosts(); + } } } }; @@ -1227,7 +1188,7 @@ public class ReaderPostListFragment extends Fragment { checkCurrentTag(); getSpinnerAdapter().reloadTags(); if (!TextUtils.isEmpty(newCurrentTag)) { - setCurrentTagName(newCurrentTag); + setCurrentTag(new ReaderTag(newCurrentTag, ReaderTagType.FOLLOWED), true); } } @@ -1359,4 +1320,155 @@ public class ReaderPostListFragment extends Fragment { ReaderTagActions.TagAction action = (isAskingToFollow ? ReaderTagActions.TagAction.ADD : ReaderTagActions.TagAction.DELETE); ReaderTagActions.performTagAction(getCurrentTag(), action, null); } + + /* + * called from adapter when user taps a post + */ + @Override + public void onPostSelected(long blogId, long postId) { + if (!isAdded()) return; + + AnalyticsTracker.track(AnalyticsTracker.Stat.READER_OPENED_ARTICLE); + + switch (getPostListType()) { + case TAG_FOLLOWED: + case TAG_PREVIEW: + ReaderActivityLauncher.showReaderPostPagerForTag( + getActivity(), + getCurrentTag(), + getPostListType(), + blogId, + postId); + break; + case BLOG_PREVIEW: + ReaderActivityLauncher.showReaderPostPagerForBlog( + getActivity(), + blogId, + postId); + break; + } + } + + /* + * called from adapter when user taps a tag on a post + */ + @Override + public void onTagSelected(String tagName) { + if (!isAdded()) return; + + ReaderTag tag = new ReaderTag(tagName, ReaderTagType.FOLLOWED); + if (getPostListType().equals(ReaderTypes.ReaderPostListType.TAG_PREVIEW)) { + // user is already previewing a tag, so change current tag in existing preview + setCurrentTag(tag, true); + } else { + // user isn't previewing a tag, so open in tag preview + ReaderActivityLauncher.showReaderTagPreview(getActivity(), tag); + } + } + + /* + * called when user taps dropdown arrow icon next to a post - shows a popup menu + * that enables blocking the blog the post is in + */ + @Override + public void onShowPostPopup(View view, final ReaderPost post) { + if (view == null || post == null || !isAdded()) { + return; + } + + PopupMenu popup = new PopupMenu(getActivity(), view); + MenuItem menuItem = popup.getMenu().add(getString(R.string.reader_menu_block_blog)); + menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + blockBlogForPost(post); + return true; + } + }); + popup.show(); + } + + /* + * called from activity to handle reader-related onActivityResult + */ + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + switch (requestCode) { + // user just returned from the tags/subs activity + case ReaderConstants.INTENT_READER_SUBS: + if (data != null) { + boolean tagsChanged = data.getBooleanExtra(ReaderSubsActivity.KEY_TAGS_CHANGED, false); + boolean blogsChanged = data.getBooleanExtra(ReaderSubsActivity.KEY_BLOGS_CHANGED, false); + // reload tags if they were changed, and set the last tag added as the current one + if (tagsChanged) { + String lastAddedTag = data.getStringExtra(ReaderSubsActivity.KEY_LAST_ADDED_TAG_NAME); + doTagsChanged(lastAddedTag); + } + // refresh posts if blogs changed and user is viewing "Blogs I Follow" + if (blogsChanged + && getPostListType() == ReaderTypes.ReaderPostListType.TAG_FOLLOWED + && hasCurrentTag() + && getCurrentTag().isBlogsIFollow()) { + refreshPosts(); + } + } + break; + + // user just returned from reblogging activity, reload the displayed post if reblogging + // succeeded + case ReaderConstants.INTENT_READER_REBLOG: + if (resultCode == Activity.RESULT_OK && data != null) { + long blogId = data.getLongExtra(ReaderConstants.ARG_BLOG_ID, 0); + long postId = data.getLongExtra(ReaderConstants.ARG_POST_ID, 0); + reloadPost(ReaderPostTable.getPost(blogId, postId, true)); + } + break; + } + } + + /* + * purge reader db if it hasn't been done yet, but only if there's an active connection + * since we don't want to purge posts that the user would expect to see when offline + */ + private void purgeDatabaseIfNeeded() { + if (EventBus.getDefault().getStickyEvent(ReaderEvents.HasPurgedDatabase.class) == null + && NetworkUtils.isNetworkAvailable(getActivity())) { + AppLog.d(T.READER, "reader post list > purging database"); + ReaderDatabase.purgeAsync(); + EventBus.getDefault().postSticky(new ReaderEvents.HasPurgedDatabase()); + } + } + + /* + * initial update performed the first time the user opens the reader + */ + private void performInitialUpdateIfNeeded() { + if (EventBus.getDefault().getStickyEvent(ReaderEvents.HasPerformedInitialUpdate.class) == null + && NetworkUtils.isNetworkAvailable(getActivity())) { + // update current user to ensure we have their user_id as well as their latest info + // in case they changed their avatar, name, etc. since last time + AppLog.d(T.READER, "reader post list > updating current user"); + ReaderUserActions.updateCurrentUser(); + + EventBus.getDefault().postSticky(new ReaderEvents.HasPerformedInitialUpdate()); + } + } + + /* + * start background service to get the latest followed tags and blogs if it's time to do so + */ + void updateFollowedTagsAndBlogsIfNeeded() { + ReaderEvents.UpdatedFollowedTagsAndBlogs lastUpdateEvent = + EventBus.getDefault().getStickyEvent(ReaderEvents.UpdatedFollowedTagsAndBlogs.class); + if (lastUpdateEvent != null && lastUpdateEvent.minutesSinceLastUpdate() < 120) { + return; + } + + AppLog.d(T.READER, "reader post list > updating tags and blogs"); + EventBus.getDefault().postSticky(new ReaderEvents.UpdatedFollowedTagsAndBlogs()); + + ReaderUpdateService.startService(getActivity(), + EnumSet.of(ReaderUpdateService.UpdateTask.TAGS, + ReaderUpdateService.UpdateTask.FOLLOWED_BLOGS)); + } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderTypes.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderTypes.java index 307f94836..74718bddd 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderTypes.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderTypes.java @@ -18,9 +18,4 @@ public class ReaderTypes { return this.equals(TAG_PREVIEW) || this.equals(BLOG_PREVIEW); } } - - protected static enum RefreshType { - AUTOMATIC, // refresh was performed by the app without user requesting it - MANUAL // refresh was requested by the user - } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/actions/ReaderUserActions.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/actions/ReaderUserActions.java index 0f2cce72b..93cf20fcf 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/actions/ReaderUserActions.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/actions/ReaderUserActions.java @@ -15,28 +15,17 @@ public class ReaderUserActions { /* * request the current user's info, update locally if different than existing local */ - public static void updateCurrentUser(final ReaderActions.UpdateResultListener resultListener) { + public static void updateCurrentUser() { com.wordpress.rest.RestRequest.Listener listener = new RestRequest.Listener() { @Override public void onResponse(JSONObject jsonObject) { - final ReaderActions.UpdateResult result; - if (jsonObject == null) { - result = ReaderActions.UpdateResult.FAILED; - } else { + if (jsonObject != null) { final ReaderUser serverUser = ReaderUser.fromJson(jsonObject); final ReaderUser localUser = ReaderUserTable.getCurrentUser(); - if (serverUser == null) { - result = ReaderActions.UpdateResult.FAILED; - } else if (serverUser.isSameUser(localUser)) { - result = ReaderActions.UpdateResult.UNCHANGED; - } else { + if (serverUser != null && !serverUser.isSameUser(localUser)) { setCurrentUser(serverUser); - result = ReaderActions.UpdateResult.CHANGED; } } - - if (resultListener != null) - resultListener.onUpdateResult(result); } }; @@ -44,8 +33,6 @@ public class ReaderUserActions { @Override public void onErrorResponse(VolleyError volleyError) { AppLog.e(T.READER, volleyError); - if (resultListener != null) - resultListener.onUpdateResult(ReaderActions.UpdateResult.FAILED); } }; |