From 0fa03cba2150a2225677d6abe611c63510e428ee Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Mon, 20 Aug 2018 22:33:00 +0800 Subject: Rename some classes and layout resources. Feature added: view posts in ViewSubredditDetailActivity. --- .../infinityforreddit/BestPostFragment.java | 249 --------------- .../infinityforreddit/FetchComment.java | 2 +- .../infinityforreddit/FetchSubredditData.java | 2 +- .../infinityforreddit/MainActivity.java | 14 +- .../infinityforreddit/ParsePost.java | 2 +- .../infinityforreddit/PostFragment.java | 346 +++++++++++++++++++++ .../PostPaginationScrollListener.java | 103 +++++- .../infinityforreddit/PostRecyclerViewAdapter.java | 2 +- .../infinityforreddit/RedditUtils.java | 8 +- .../ViewSubredditDetailActivity.java | 29 +- .../res/layout/activity_view_subreddit_detail.xml | 1 + app/src/main/res/layout/fragment_best_post.xml | 28 -- app/src/main/res/layout/fragment_post.xml | 30 ++ app/src/main/res/layout/item_best_post.xml | 180 ----------- .../main/res/layout/item_footer_progress_bar.xml | 2 + app/src/main/res/layout/item_post.xml | 180 +++++++++++ 16 files changed, 696 insertions(+), 482 deletions(-) delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/BestPostFragment.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/PostFragment.java delete mode 100644 app/src/main/res/layout/fragment_best_post.xml create mode 100644 app/src/main/res/layout/fragment_post.xml delete mode 100644 app/src/main/res/layout/item_best_post.xml create mode 100644 app/src/main/res/layout/item_post.xml (limited to 'app/src') diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/BestPostFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/BestPostFragment.java deleted file mode 100644 index 87594ef0..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/BestPostFragment.java +++ /dev/null @@ -1,249 +0,0 @@ -package ml.docilealligator.infinityforreddit; - - -import android.support.v4.app.Fragment; -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Context; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.design.widget.CoordinatorLayout; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.Snackbar; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ProgressBar; -import android.widget.Toast; - -import com.android.volley.AuthFailureError; -import com.android.volley.Request; -import com.android.volley.RequestQueue; -import com.android.volley.Response; -import com.android.volley.VolleyError; -import com.android.volley.toolbox.StringRequest; -import com.android.volley.toolbox.Volley; - -import java.util.ArrayList; -import java.util.Map; - - -/** - * A simple {@link Fragment} subclass. - */ -public class BestPostFragment extends Fragment { - - private CoordinatorLayout mCoordinatorLayout; - private RecyclerView mBestPostRecyclerView; - private LinearLayoutManager mLinearLayoutManager; - private ProgressBar mProgressBar; - private ArrayList mPostData; - private String mLastItem; - private PaginationSynchronizer mPaginationSynchronizer; - private PostRecyclerViewAdapter mAdapter; - - private String bestPostDataParcelableState = "BPDPS"; - private String lastItemState = "LIS"; - private String paginationSynchronizerState = "PSS"; - - private RequestQueue mRequestQueue; - private RequestQueue mPaginationRequestQueue; - private RequestQueue mAcquireAccessTokenRequestQueue; - private RequestQueue mVoteThingRequestQueue; - - public BestPostFragment() { - // Required empty public constructor - } - - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - if(savedInstanceState != null) { - if(savedInstanceState.containsKey(bestPostDataParcelableState)) { - mPostData = savedInstanceState.getParcelableArrayList(bestPostDataParcelableState); - mLastItem = savedInstanceState.getString(lastItemState); - mAdapter = new PostRecyclerViewAdapter(getActivity(), mPostData, mPaginationSynchronizer, mVoteThingRequestQueue, mAcquireAccessTokenRequestQueue); - mBestPostRecyclerView.setAdapter(mAdapter); - mBestPostRecyclerView.addOnScrollListener(new PostPaginationScrollListener(getActivity(), mLinearLayoutManager, mAdapter, mLastItem, mPostData, mPaginationSynchronizer, - mAcquireAccessTokenRequestQueue, mPaginationSynchronizer.isLoading(), mPaginationSynchronizer.isLoadSuccess())); - mProgressBar.setVisibility(View.GONE); - } else { - queryBestPost(1); - } - } - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - - if(mRequestQueue != null) { - mRequestQueue.cancelAll(this); - } - - if(mAcquireAccessTokenRequestQueue != null) { - mAcquireAccessTokenRequestQueue.cancelAll(AcquireAccessToken.class); - } - - if(mVoteThingRequestQueue != null) { - mVoteThingRequestQueue.cancelAll(VoteThing.class); - } - - if(mPaginationRequestQueue != null) { - mPaginationRequestQueue.cancelAll(PostPaginationScrollListener.class); - } - - if(mPostData != null) { - outState.putParcelableArrayList(bestPostDataParcelableState, mPostData); - outState.putString(lastItemState, mLastItem); - outState.putParcelable(paginationSynchronizerState, mPaginationSynchronizer); - } - } - - @Override - public void onResume() { - super.onResume(); - if(mAdapter != null) { - mAdapter.setCanStartActivity(true); - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - // Inflate the layout for this fragment - View rootView = inflater.inflate(R.layout.fragment_best_post, container, false); - mCoordinatorLayout = rootView.findViewById(R.id.coordinator_layout_best_post_fragment); - mBestPostRecyclerView = rootView.findViewById(R.id.recycler_view_best_post_fragment); - mLinearLayoutManager = new LinearLayoutManager(getActivity()); - mBestPostRecyclerView.setLayoutManager(mLinearLayoutManager); - mProgressBar = rootView.findViewById(R.id.progress_bar_best_post_fragment); - FloatingActionButton fab = rootView.findViewById(R.id.fab_best_post_fragment); - fab.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } - }); - - mRequestQueue = Volley.newRequestQueue(getActivity()); - mAcquireAccessTokenRequestQueue = Volley.newRequestQueue(getActivity()); - mVoteThingRequestQueue = Volley.newRequestQueue(getActivity()); - - if(savedInstanceState != null && savedInstanceState.getParcelable(paginationSynchronizerState) != null) { - mPaginationSynchronizer = savedInstanceState.getParcelable(paginationSynchronizerState); - } else { - mPaginationSynchronizer = new PaginationSynchronizer(); - queryBestPost(1); - } - - LastItemSynchronizer lastItemSynchronizer = new LastItemSynchronizer() { - @Override - public void lastItemChanged(String lastItem) { - mLastItem = lastItem; - } - }; - mPaginationSynchronizer.setLastItemSynchronizer(lastItemSynchronizer); - - PaginationRequestQueueSynchronizer paginationRequestQueueSynchronizer = new PaginationRequestQueueSynchronizer() { - @Override - public void passQueue(RequestQueue q) { - mPaginationRequestQueue = q; - } - }; - mPaginationSynchronizer.setPaginationRequestQueueSynchronizer(paginationRequestQueueSynchronizer); - - return rootView; - } - - private void queryBestPost(final int refreshTime) { - if(refreshTime < 0) { - showErrorSnackbar(); - return; - } - - mProgressBar.setVisibility(View.VISIBLE); - - Uri uri = Uri.parse(RedditUtils.OAUTH_API_BASE_URI + RedditUtils.BEST_POST_SUFFIX) - .buildUpon().appendQueryParameter(RedditUtils.RAW_JSON_KEY, RedditUtils.RAW_JSON_VALUE) - .build(); - - StringRequest bestPostRequest = new StringRequest(Request.Method.GET, uri.toString(), new Response.Listener() { - @Override - public void onResponse(String response) { - if(getActivity() != null) { - ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText("response", response); - clipboard.setPrimaryClip(clip); - //new ParsePostDataAsyncTask(response, accessToken).execute(); - new ParsePost(getActivity(), new ParsePost.ParsePostListener() { - @Override - public void onParsePostSuccess(ArrayList bestPostData, String lastItem) { - mPostData = bestPostData; - mLastItem = lastItem; - mAdapter = new PostRecyclerViewAdapter(getActivity(), bestPostData, mPaginationSynchronizer, mVoteThingRequestQueue, mAcquireAccessTokenRequestQueue); - - mBestPostRecyclerView.setAdapter(mAdapter); - mBestPostRecyclerView.addOnScrollListener(new PostPaginationScrollListener(getActivity(), mLinearLayoutManager, mAdapter, lastItem, bestPostData, mPaginationSynchronizer, - mAcquireAccessTokenRequestQueue, mPaginationSynchronizer.isLoading(), mPaginationSynchronizer.isLoadSuccess())); - mProgressBar.setVisibility(View.GONE); - } - - @Override - public void onParsePostFail() { - Toast.makeText(getActivity(), "Error parsing data", Toast.LENGTH_SHORT).show(); - Log.i("Best post fetch error", "Error parsing data"); - mProgressBar.setVisibility(View.GONE); - } - }).parseBestPost(response, new ArrayList()); - } - } - }, new Response.ErrorListener() { - @Override - public void onErrorResponse(VolleyError error) { - if (error instanceof AuthFailureError) { - // Error indicating that there was an Authentication Failure while performing the request - // Access token expired - new AcquireAccessToken(getActivity()).refreshAccessToken(mAcquireAccessTokenRequestQueue, - new AcquireAccessToken.AcquireAccessTokenListener() { - @Override - public void onAcquireAccessTokenSuccess() { - queryBestPost(refreshTime - 1); - } - - @Override - public void onAcquireAccessTokenFail() {} - }); - } else { - Log.i("best post fetch error", error.toString()); - showErrorSnackbar(); - } - } - }) { - @Override - public Map getHeaders() { - String accessToken = getActivity().getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE).getString(SharedPreferencesUtils.ACCESS_TOKEN_KEY, ""); - return RedditUtils.getOAuthHeader(accessToken); - } - }; - bestPostRequest.setTag(BestPostFragment.class); - mRequestQueue.add(bestPostRequest); - } - - private void showErrorSnackbar() { - mProgressBar.setVisibility(View.GONE); - Snackbar snackbar = Snackbar.make(mCoordinatorLayout, "Error getting best post", Snackbar.LENGTH_INDEFINITE); - snackbar.setAction(R.string.retry, new View.OnClickListener() { - @Override - public void onClick(View view) { - queryBestPost(1); - } - }); - snackbar.show(); - } -} \ No newline at end of file diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java index 3721947e..6c23036e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java @@ -28,7 +28,7 @@ class FetchComment { void queryComment(FetchCommentListener fetchCommentListener) { mFetchCommentListener = fetchCommentListener; - Uri uri = Uri.parse(RedditUtils.getQueryCommentUri(subredditName, article)) + Uri uri = Uri.parse(RedditUtils.getQueryCommentUrl(subredditName, article)) .buildUpon().appendQueryParameter(RedditUtils.RAW_JSON_KEY, RedditUtils.RAW_JSON_VALUE) .build(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubredditData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubredditData.java index 00d07c26..af7b6029 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubredditData.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubredditData.java @@ -23,7 +23,7 @@ class FetchSubredditData { void querySubredditData(FetchSubredditDataListener fetchSubredditDataListener) { mFetchSubredditDataListener = fetchSubredditDataListener; - StringRequest commentRequest = new StringRequest(Request.Method.GET, RedditUtils.getQuerySubredditDataUri(subredditName), new Response.Listener() { + StringRequest commentRequest = new StringRequest(Request.Method.GET, RedditUtils.getQuerySubredditDataUrl(subredditName), new Response.Listener() { @Override public void onResponse(String response) { mFetchSubredditDataListener.onFetchSubredditDataSuccess(response); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java index b07bbd4c..b462006e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java @@ -5,11 +5,11 @@ import android.arch.lifecycle.ViewModelProviders; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentTransaction; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; @@ -79,9 +79,15 @@ public class MainActivity extends AppCompatActivity { startActivity(loginIntent); } else { if(savedInstanceState == null) { - FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); - mFragment = new BestPostFragment(); - fragmentTransaction.replace(R.id.frame_layout_content_main, mFragment).commit(); + mFragment = new PostFragment(); + Uri uri = Uri.parse(RedditUtils.OAUTH_API_BASE_URI + RedditUtils.BEST_POST_SUFFIX) + .buildUpon().appendQueryParameter(RedditUtils.RAW_JSON_KEY, RedditUtils.RAW_JSON_VALUE) + .build(); + Bundle bundle = new Bundle(); + bundle.putString(PostFragment.QUERY_POST_URL_KEY, uri.toString()); + bundle.putBoolean(PostFragment.IS_BEST_POST_KEY, true); + mFragment.setArguments(bundle); + getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_content_main, mFragment).commit(); } else { mFragment = getSupportFragmentManager().getFragment(savedInstanceState, "outStateFragment"); getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_content_main, mFragment).commit(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java index 579d5c04..aed3a1fc 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java @@ -32,7 +32,7 @@ class ParsePost { mParseBetPostListener = parsePostListener; } - void parseBestPost(String response, ArrayList postData) { + void parsePost(String response, ArrayList postData) { new ParsePostDataAsyncTask(response, postData).execute(); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostFragment.java new file mode 100644 index 00000000..49220d94 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PostFragment.java @@ -0,0 +1,346 @@ +package ml.docilealligator.infinityforreddit; + + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.CoordinatorLayout; +import android.support.design.widget.Snackbar; +import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ProgressBar; +import android.widget.Toast; + +import com.android.volley.AuthFailureError; +import com.android.volley.Request; +import com.android.volley.RequestQueue; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.android.volley.toolbox.StringRequest; +import com.android.volley.toolbox.Volley; + +import java.util.ArrayList; +import java.util.Map; + + +/** + * A simple {@link Fragment} subclass. + */ +public class PostFragment extends Fragment { + + static final String QUERY_POST_URL_KEY = "QPUK"; + static final String IS_BEST_POST_KEY = "IBPK"; + + private CoordinatorLayout mCoordinatorLayout; + private RecyclerView mPostRecyclerView; + private LinearLayoutManager mLinearLayoutManager; + private ProgressBar mProgressBar; + private ArrayList mPostData; + private String mLastItem; + private PaginationSynchronizer mPaginationSynchronizer; + private PostRecyclerViewAdapter mAdapter; + + private boolean mIsBestPost; + private String mQueryPostUrl; + private String PostDataParcelableState = "BPDPS"; + private String lastItemState = "LIS"; + private String paginationSynchronizerState = "PSS"; + + private RequestQueue mRequestQueue; + private RequestQueue mPaginationRequestQueue; + private RequestQueue mAcquireAccessTokenRequestQueue; + private RequestQueue mVoteThingRequestQueue; + + public PostFragment() { + // Required empty public constructor + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + if(savedInstanceState != null) { + if(savedInstanceState.containsKey(PostDataParcelableState)) { + mPostData = savedInstanceState.getParcelableArrayList(PostDataParcelableState); + mLastItem = savedInstanceState.getString(lastItemState); + mAdapter = new PostRecyclerViewAdapter(getActivity(), mPostData, mPaginationSynchronizer, mVoteThingRequestQueue, mAcquireAccessTokenRequestQueue); + mPostRecyclerView.setAdapter(mAdapter); + mPostRecyclerView.addOnScrollListener(new PostPaginationScrollListener( + getActivity(), mLinearLayoutManager, mAdapter, mLastItem, mPostData, + mPaginationSynchronizer, mAcquireAccessTokenRequestQueue, + mQueryPostUrl, mIsBestPost, + mPaginationSynchronizer.isLoading(), mPaginationSynchronizer.isLoadSuccess())); + mProgressBar.setVisibility(View.GONE); + } else { + if(mIsBestPost) { + queryBestPost(mQueryPostUrl, 1); + } else { + queryPost(mQueryPostUrl, 1); + } + } + } + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + + if(mRequestQueue != null) { + mRequestQueue.cancelAll(this); + } + + if(mAcquireAccessTokenRequestQueue != null) { + mAcquireAccessTokenRequestQueue.cancelAll(AcquireAccessToken.class); + } + + if(mVoteThingRequestQueue != null) { + mVoteThingRequestQueue.cancelAll(VoteThing.class); + } + + if(mPaginationRequestQueue != null) { + mPaginationRequestQueue.cancelAll(PostPaginationScrollListener.class); + } + + if(mPostData != null) { + outState.putParcelableArrayList(PostDataParcelableState, mPostData); + outState.putString(lastItemState, mLastItem); + outState.putParcelable(paginationSynchronizerState, mPaginationSynchronizer); + } + } + + @Override + public void onResume() { + super.onResume(); + if(mAdapter != null) { + mAdapter.setCanStartActivity(true); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View rootView = inflater.inflate(R.layout.fragment_post, container, false); + mCoordinatorLayout = rootView.findViewById(R.id.coordinator_layout_post_fragment); + mPostRecyclerView = rootView.findViewById(R.id.recycler_view_post_fragment); + mLinearLayoutManager = new LinearLayoutManager(getActivity()); + mPostRecyclerView.setLayoutManager(mLinearLayoutManager); + mProgressBar = rootView.findViewById(R.id.progress_bar_post_fragment); + /*FloatingActionButton fab = rootView.findViewById(R.id.fab_post_fragment); + fab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + } + });*/ + + mRequestQueue = Volley.newRequestQueue(getActivity()); + mAcquireAccessTokenRequestQueue = Volley.newRequestQueue(getActivity()); + mVoteThingRequestQueue = Volley.newRequestQueue(getActivity()); + + mIsBestPost = getArguments().getBoolean(IS_BEST_POST_KEY); + mQueryPostUrl = getArguments().getString(QUERY_POST_URL_KEY); + + if(savedInstanceState != null && savedInstanceState.getParcelable(paginationSynchronizerState) != null) { + mPaginationSynchronizer = savedInstanceState.getParcelable(paginationSynchronizerState); + } else { + mPaginationSynchronizer = new PaginationSynchronizer(); + if(mIsBestPost) { + queryBestPost(mQueryPostUrl, 1); + } else { + queryPost(mQueryPostUrl, 1); + } + } + + LastItemSynchronizer lastItemSynchronizer = new LastItemSynchronizer() { + @Override + public void lastItemChanged(String lastItem) { + mLastItem = lastItem; + } + }; + mPaginationSynchronizer.setLastItemSynchronizer(lastItemSynchronizer); + + PaginationRequestQueueSynchronizer paginationRequestQueueSynchronizer = new PaginationRequestQueueSynchronizer() { + @Override + public void passQueue(RequestQueue q) { + mPaginationRequestQueue = q; + } + }; + mPaginationSynchronizer.setPaginationRequestQueueSynchronizer(paginationRequestQueueSynchronizer); + + return rootView; + } + + private void queryBestPost(final String queryPostUrl, final int refreshTime) { + if(refreshTime < 0) { + showErrorSnackbar(); + return; + } + + mProgressBar.setVisibility(View.VISIBLE); + + /*Uri uri = Uri.parse(RedditUtils.OAUTH_API_BASE_URI + RedditUtils.BEST_POST_SUFFIX) + .buildUpon().appendQueryParameter(RedditUtils.RAW_JSON_KEY, RedditUtils.RAW_JSON_VALUE) + .build();*/ + + StringRequest postRequest = new StringRequest(Request.Method.GET, mQueryPostUrl, new Response.Listener() { + @Override + public void onResponse(String response) { + if(getActivity() != null) { + ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText("response", response); + clipboard.setPrimaryClip(clip); + //new ParsePostDataAsyncTask(response, accessToken).execute(); + new ParsePost(getActivity(), new ParsePost.ParsePostListener() { + @Override + public void onParsePostSuccess(ArrayList postData, String lastItem) { + mPostData = postData; + mLastItem = lastItem; + mAdapter = new PostRecyclerViewAdapter(getActivity(), postData, mPaginationSynchronizer, mVoteThingRequestQueue, mAcquireAccessTokenRequestQueue); + + mPostRecyclerView.setAdapter(mAdapter); + mPostRecyclerView.addOnScrollListener(new PostPaginationScrollListener( + getActivity(), mLinearLayoutManager, mAdapter, lastItem, postData, + mPaginationSynchronizer, mAcquireAccessTokenRequestQueue, + mQueryPostUrl, mIsBestPost, + mPaginationSynchronizer.isLoading(), mPaginationSynchronizer.isLoadSuccess())); + mProgressBar.setVisibility(View.GONE); + } + + @Override + public void onParsePostFail() { + Toast.makeText(getActivity(), "Error parsing data", Toast.LENGTH_SHORT).show(); + Log.i("Post fetch error", "Error parsing data"); + mProgressBar.setVisibility(View.GONE); + } + }).parsePost(response, new ArrayList()); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + if (error instanceof AuthFailureError) { + // Error indicating that there was an Authentication Failure while performing the request + // Access token expired + new AcquireAccessToken(getActivity()).refreshAccessToken(mAcquireAccessTokenRequestQueue, + new AcquireAccessToken.AcquireAccessTokenListener() { + @Override + public void onAcquireAccessTokenSuccess() { + queryBestPost(queryPostUrl, refreshTime - 1); + } + + @Override + public void onAcquireAccessTokenFail() {} + }); + } else { + Log.i("Post fetch error", error.toString()); + showErrorSnackbar(); + } + } + }) { + @Override + public Map getHeaders() { + String accessToken = getActivity().getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE).getString(SharedPreferencesUtils.ACCESS_TOKEN_KEY, ""); + return RedditUtils.getOAuthHeader(accessToken); + } + }; + postRequest.setTag(PostFragment.class); + mRequestQueue.add(postRequest); + } + + private void queryPost(final String queryPostUrl, final int refreshTime) { + if(refreshTime < 0) { + showErrorSnackbar(); + return; + } + + mProgressBar.setVisibility(View.VISIBLE); + + Uri uri = Uri.parse(RedditUtils.OAUTH_API_BASE_URI + RedditUtils.BEST_POST_SUFFIX) + .buildUpon().appendQueryParameter(RedditUtils.RAW_JSON_KEY, RedditUtils.RAW_JSON_VALUE) + .build(); + + StringRequest postRequest = new StringRequest(Request.Method.GET, queryPostUrl, new Response.Listener() { + @Override + public void onResponse(String response) { + if(getActivity() != null) { + ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText("response", response); + clipboard.setPrimaryClip(clip); + //new ParsePostDataAsyncTask(response, accessToken).execute(); + new ParsePost(getActivity(), new ParsePost.ParsePostListener() { + @Override + public void onParsePostSuccess(ArrayList postData, String lastItem) { + mPostData = postData; + mLastItem = lastItem; + mAdapter = new PostRecyclerViewAdapter(getActivity(), postData, mPaginationSynchronizer, mVoteThingRequestQueue, mAcquireAccessTokenRequestQueue); + + mPostRecyclerView.setAdapter(mAdapter); + mPostRecyclerView.addOnScrollListener(new PostPaginationScrollListener( + getActivity(), mLinearLayoutManager, mAdapter, lastItem, postData, + mPaginationSynchronizer, mAcquireAccessTokenRequestQueue, + mQueryPostUrl, mIsBestPost, + mPaginationSynchronizer.isLoading(), mPaginationSynchronizer.isLoadSuccess())); + mProgressBar.setVisibility(View.GONE); + } + + @Override + public void onParsePostFail() { + Toast.makeText(getActivity(), "Error parsing data", Toast.LENGTH_SHORT).show(); + Log.i("Post fetch error", "Error parsing data"); + mProgressBar.setVisibility(View.GONE); + } + }).parsePost(response, new ArrayList()); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + if (error instanceof AuthFailureError) { + // Error indicating that there was an Authentication Failure while performing the request + // Access token expired + new AcquireAccessToken(getActivity()).refreshAccessToken(mAcquireAccessTokenRequestQueue, + new AcquireAccessToken.AcquireAccessTokenListener() { + @Override + public void onAcquireAccessTokenSuccess() { + queryPost(queryPostUrl, refreshTime - 1); + } + + @Override + public void onAcquireAccessTokenFail() {} + }); + } else { + Log.i("Post fetch error", error.toString()); + showErrorSnackbar(); + } + } + }); + postRequest.setTag(PostFragment.class); + mRequestQueue.add(postRequest); + } + + private void showErrorSnackbar() { + mProgressBar.setVisibility(View.GONE); + Snackbar snackbar = Snackbar.make(mCoordinatorLayout, "Error getting post", Snackbar.LENGTH_INDEFINITE); + snackbar.setAction(R.string.retry, new View.OnClickListener() { + @Override + public void onClick(View view) { + if(mIsBestPost) { + queryBestPost(mQueryPostUrl, 1); + } else { + queryPost(mQueryPostUrl, 1); + } + } + }); + snackbar.show(); + } +} \ No newline at end of file diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostPaginationScrollListener.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostPaginationScrollListener.java index 19ab4109..2ee6478a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostPaginationScrollListener.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PostPaginationScrollListener.java @@ -4,6 +4,7 @@ import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; import android.net.Uri; +import android.support.annotation.NonNull; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; @@ -34,14 +35,18 @@ class PostPaginationScrollListener extends RecyclerView.OnScrollListener { private LastItemSynchronizer mLastItemSynchronizer; private PaginationRequestQueueSynchronizer mPaginationRequestQueueSynchronizer; + private String mQueryPostUrl; + private boolean isBestPost; private boolean isLoading; private boolean loadSuccess; private String mLastItem; private RequestQueue mRequestQueue; private RequestQueue mAcquireAccessTokenRequestQueue; - PostPaginationScrollListener(Context context, LinearLayoutManager layoutManager, PostRecyclerViewAdapter adapter, String lastItem, ArrayList postData, PaginationSynchronizer paginationSynchronizer, - RequestQueue acquireAccessTokenRequestQueue, boolean isLoading, boolean loadSuccess) { + PostPaginationScrollListener(Context context, LinearLayoutManager layoutManager, PostRecyclerViewAdapter adapter, + String lastItem, ArrayList postData, PaginationSynchronizer paginationSynchronizer, + RequestQueue acquireAccessTokenRequestQueue, final String queryPostUrl, + final boolean isBestPost, boolean isLoading, boolean loadSuccess) { if(context != null) { this.mContext = context; this.mLayoutManager = layoutManager; @@ -50,6 +55,8 @@ class PostPaginationScrollListener extends RecyclerView.OnScrollListener { this.mPostData = postData; this.mPaginationSynchronizer = paginationSynchronizer; this.mAcquireAccessTokenRequestQueue = acquireAccessTokenRequestQueue; + this.mQueryPostUrl = queryPostUrl; + this.isBestPost = isBestPost; this.isLoading = isLoading; this.loadSuccess = loadSuccess; @@ -58,7 +65,11 @@ class PostPaginationScrollListener extends RecyclerView.OnScrollListener { mPaginationRetryNotifier = new PaginationRetryNotifier() { @Override public void retry() { - fetchBestPost(1); + if(isBestPost) { + fetchBestPost(queryPostUrl, 1); + } else { + fetchPost(queryPostUrl, 1); + } } }; mPaginationSynchronizer.setPaginationRetryNotifier(mPaginationRetryNotifier); @@ -69,7 +80,7 @@ class PostPaginationScrollListener extends RecyclerView.OnScrollListener { } @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if(!isLoading && loadSuccess) { int visibleItemCount = mLayoutManager.getChildCount(); @@ -77,13 +88,17 @@ class PostPaginationScrollListener extends RecyclerView.OnScrollListener { int firstVisibleItemPosition = mLayoutManager.findFirstVisibleItemPosition(); if((visibleItemCount + firstVisibleItemPosition >= totalItemCount) && firstVisibleItemPosition >= 0) { - fetchBestPost(1); + if(isBestPost) { + fetchBestPost(mQueryPostUrl, 1); + } else { + fetchPost(mQueryPostUrl, 1); + } } } } - private void fetchBestPost(final int refreshTime) { + private void fetchBestPost(final String queryPostUrl, final int refreshTime) { if(refreshTime < 0) { loadFailed(); return; @@ -93,9 +108,8 @@ class PostPaginationScrollListener extends RecyclerView.OnScrollListener { loadSuccess = false; mPaginationSynchronizer.setLoading(true); - Uri uri = Uri.parse(RedditUtils.OAUTH_API_BASE_URI + RedditUtils.BEST_POST_SUFFIX) - .buildUpon().appendQueryParameter(RedditUtils.AFTER_KEY, mLastItem) - .appendQueryParameter(RedditUtils.RAW_JSON_KEY, RedditUtils.RAW_JSON_VALUE).build(); + Uri uri = Uri.parse(queryPostUrl) + .buildUpon().appendQueryParameter(RedditUtils.AFTER_KEY, mLastItem).build(); StringRequest bestPostRequest = new StringRequest(Request.Method.GET, uri.toString(), new Response.Listener() { @Override @@ -122,7 +136,7 @@ class PostPaginationScrollListener extends RecyclerView.OnScrollListener { Log.i("Best post", "Error parsing data"); loadFailed(); } - }).parseBestPost(response, mPostData); + }).parsePost(response, mPostData); } }, new Response.ErrorListener() { @Override @@ -133,7 +147,7 @@ class PostPaginationScrollListener extends RecyclerView.OnScrollListener { new AcquireAccessToken.AcquireAccessTokenListener() { @Override public void onAcquireAccessTokenSuccess() { - fetchBestPost(refreshTime - 1); + fetchBestPost(queryPostUrl, refreshTime - 1); } @Override @@ -157,6 +171,73 @@ class PostPaginationScrollListener extends RecyclerView.OnScrollListener { mRequestQueue.add(bestPostRequest); } + private void fetchPost(final String queryPostUrl, final int refreshTime) { + if(refreshTime < 0) { + loadFailed(); + return; + } + + isLoading = true; + loadSuccess = false; + mPaginationSynchronizer.setLoading(true); + + Uri uri = Uri.parse(queryPostUrl) + .buildUpon().appendQueryParameter(RedditUtils.AFTER_KEY, mLastItem).build(); + + StringRequest bestPostRequest = new StringRequest(Request.Method.GET, uri.toString(), new Response.Listener() { + @Override + public void onResponse(String response) { + ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText("response", response); + clipboard.setPrimaryClip(clip); + new ParsePost(mContext, new ParsePost.ParsePostListener() { + @Override + public void onParsePostSuccess(ArrayList bestPostData, String lastItem) { + mAdapter.notifyDataSetChanged(); + mLastItem = lastItem; + mLastItemSynchronizer.lastItemChanged(mLastItem); + + isLoading = false; + loadSuccess = true; + mPaginationSynchronizer.setLoading(false); + mPaginationSynchronizer.setLoadingState(true); + } + + @Override + public void onParsePostFail() { + Toast.makeText(mContext, "Error parsing data", Toast.LENGTH_SHORT).show(); + Log.i("Best post", "Error parsing data"); + loadFailed(); + } + }).parsePost(response, mPostData); + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + if (error instanceof AuthFailureError) { + //Access token expired + new AcquireAccessToken(mContext).refreshAccessToken(mAcquireAccessTokenRequestQueue, + new AcquireAccessToken.AcquireAccessTokenListener() { + @Override + public void onAcquireAccessTokenSuccess() { + fetchPost(queryPostUrl, refreshTime - 1); + } + + @Override + public void onAcquireAccessTokenFail() { + } + }); + } else { + Toast.makeText(mContext, "Error getting best post", Toast.LENGTH_SHORT).show(); + Log.i("best post", error.toString()); + loadFailed(); + } + } + }); + bestPostRequest.setTag(PostPaginationScrollListener.class); + mRequestQueue.add(bestPostRequest); + } + private void loadFailed() { isLoading = false; loadSuccess = false; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java index 101ff11f..b7a918cd 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java @@ -77,7 +77,7 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter { private final SubredditDao mSubredditDao; diff --git a/app/src/main/res/layout/activity_view_subreddit_detail.xml b/app/src/main/res/layout/activity_view_subreddit_detail.xml index 460f3fb2..ce3c4d55 100644 --- a/app/src/main/res/layout/activity_view_subreddit_detail.xml +++ b/app/src/main/res/layout/activity_view_subreddit_detail.xml @@ -4,6 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:id="@+id/coordinator_layout_view_subreddit_detail_activity" android:fitsSystemWindows="true" tools:context=".ViewSubredditDetailActivity"> diff --git a/app/src/main/res/layout/fragment_best_post.xml b/app/src/main/res/layout/fragment_best_post.xml deleted file mode 100644 index f4d24c08..00000000 --- a/app/src/main/res/layout/fragment_best_post.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_post.xml b/app/src/main/res/layout/fragment_post.xml new file mode 100644 index 00000000..e18a4a62 --- /dev/null +++ b/app/src/main/res/layout/fragment_post.xml @@ -0,0 +1,30 @@ + + + + + + + + + diff --git a/app/src/main/res/layout/item_best_post.xml b/app/src/main/res/layout/item_best_post.xml deleted file mode 100644 index 5978957c..00000000 --- a/app/src/main/res/layout/item_best_post.xml +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_footer_progress_bar.xml b/app/src/main/res/layout/item_footer_progress_bar.xml index 9f2347ec..86e1a1a9 100644 --- a/app/src/main/res/layout/item_footer_progress_bar.xml +++ b/app/src/main/res/layout/item_footer_progress_bar.xml @@ -10,6 +10,7 @@ android:id="@+id/progress_bar_footer_progress_bar_item" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginTop="8dp" android:layout_marginBottom="16dp" android:layout_gravity="center" /> @@ -17,6 +18,7 @@ android:id="@+id/relative_layout_footer_progress_bar_item" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginTop="8dp" android:layout_marginBottom="16dp" android:layout_marginLeft="16dp" android:layout_marginStart="16dp" diff --git a/app/src/main/res/layout/item_post.xml b/app/src/main/res/layout/item_post.xml new file mode 100644 index 00000000..5978957c --- /dev/null +++ b/app/src/main/res/layout/item_post.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3