From a4f664d42841175cd65a0d1d92d917906b3a695e Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Fri, 22 Feb 2019 14:55:26 +0800 Subject: [PATCH] Add a feature: Searching for posts. --- .../infinityforreddit/FetchComment.java | 2 +- .../infinityforreddit/PostDataSource.java | 91 ++++++++++++++++++- .../infinityforreddit/RedditAPI.java | 18 ++-- .../infinityforreddit/SearchActivity.java | 36 ++++++-- .../ViewPostDetailActivity.java | 20 ++-- 5 files changed, 137 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java index 0afb2978..c4a4ea00 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchComment.java @@ -1,12 +1,12 @@ package ml.docilealligator.infinityforreddit; -import androidx.annotation.NonNull; import android.util.Log; import java.util.ArrayList; import java.util.List; import java.util.Locale; +import androidx.annotation.NonNull; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java index 6c4ddb8c..c30991b3 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java @@ -1,13 +1,13 @@ package ml.docilealligator.infinityforreddit; -import androidx.lifecycle.MutableLiveData; -import androidx.paging.PageKeyedDataSource; -import androidx.annotation.NonNull; import android.util.Log; import java.util.ArrayList; import java.util.Locale; +import androidx.annotation.NonNull; +import androidx.lifecycle.MutableLiveData; +import androidx.paging.PageKeyedDataSource; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Retrofit; @@ -21,6 +21,7 @@ class PostDataSource extends PageKeyedDataSource { static final int TYPE_FRONT_PAGE = 0; static final int TYPE_SUBREDDIT = 1; static final int TYPE_USER = 2; + static final int TYPE_SEARCH = 3; private Retrofit retrofit; private String accessToken; @@ -47,11 +48,11 @@ class PostDataSource extends PageKeyedDataSource { this.onPostFetchedCallback = onPostFetchedCallback; } - PostDataSource(Retrofit retrofit, String accessToken, Locale locale, String name, int postType, OnPostFetchedCallback onPostFetchedCallback) { + PostDataSource(Retrofit retrofit, String accessToken, Locale locale, String subredditName, int postType, OnPostFetchedCallback onPostFetchedCallback) { this.retrofit = retrofit; this.accessToken = accessToken; this.locale = locale; - this.name = name; + this.name = subredditName; paginationNetworkStateLiveData = new MutableLiveData(); initialLoadStateLiveData = new MutableLiveData(); this.postType = postType; @@ -83,6 +84,9 @@ class PostDataSource extends PageKeyedDataSource { case TYPE_USER: loadUserPostsInitial(callback, null); break; + case TYPE_SEARCH: + loadSearchPostsInitial(callback); + break; } } @@ -111,6 +115,8 @@ class PostDataSource extends PageKeyedDataSource { break; case TYPE_USER: loadUserPostsAfter(params, callback); + case TYPE_SEARCH: + loadSearchPostsAfter(params, callback); } } @@ -344,6 +350,81 @@ class PostDataSource extends PageKeyedDataSource { }); } + private void loadSearchPostsInitial(@NonNull final LoadInitialCallback callback) { + RedditAPI api = retrofit.create(RedditAPI.class); + Call getPost = api.searchPosts(name, null, RedditUtils.getOAuthHeader(accessToken)); + getPost.enqueue(new Callback() { + @Override + public void onResponse(Call call, retrofit2.Response response) { + if(response.isSuccessful()) { + ParsePost.parsePost(response.body(), locale, + new ParsePost.ParsePostListener() { + @Override + public void onParsePostSuccess(ArrayList newPosts, String lastItem) { + if(newPosts.size() == 0) { + onPostFetchedCallback.noPost(); + } else { + onPostFetchedCallback.hasPost(); + } + + callback.onResult(newPosts, null, lastItem); + initialLoadStateLiveData.postValue(NetworkState.LOADED); + } + + @Override + public void onParsePostFail() { + Log.i("Post fetch error", "Error parsing data"); + initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); + } + }); + } else { + Log.i("Post fetch error", response.message()); + initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, response.message())); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + String errorMessage = t == null ? "unknown error" : t.getMessage(); + initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage)); + } + }); + } + + private void loadSearchPostsAfter(@NonNull LoadParams params, @NonNull final LoadCallback callback) { + RedditAPI api = retrofit.create(RedditAPI.class); + Call getPost = api.searchPosts(name, params.key, RedditUtils.getOAuthHeader(accessToken)); + getPost.enqueue(new Callback() { + @Override + public void onResponse(Call call, retrofit2.Response response) { + if(response.isSuccessful()) { + ParsePost.parsePost(response.body(), locale, new ParsePost.ParsePostListener() { + @Override + public void onParsePostSuccess(ArrayList newPosts, String lastItem) { + callback.onResult(newPosts, lastItem); + paginationNetworkStateLiveData.postValue(NetworkState.LOADED); + } + + @Override + public void onParsePostFail() { + Log.i("Best post", "Error parsing data"); + paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); + } + }); + } else { + Log.i("Best post", response.message()); + paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, response.message())); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + String errorMessage = t == null ? "unknown error" : t.getMessage(); + paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage)); + } + }); + } + void retry() { loadInitial(initialParams, initialCallback); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java index 95d0f173..1a1c9b37 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java @@ -58,14 +58,18 @@ public interface RedditAPI { Call getInfo(@Path("subredditNamePrefixed") String subredditNamePrefixed, @Query("id") String id); @GET("subreddits/search.json?raw_json=1&include_over_18=on") - Call searchSubreddits(@Query("q") String subredditName, @Query("after") String after); + Call searchSubreddits(@Query("q") String subredditName, @Query("after") String after, + @HeaderMap Map headers); - @GET("/profiles/search.json?raw_json=1") - Call searchProfiles(@Query("q") String profileName, @Query("after") String after); + @GET("profiles/search.json?raw_json=1") + Call searchProfiles(@Query("q") String profileName, @Query("after") String after, + @HeaderMap Map headers); - @GET("/search.json?raw_json=1") - Call searchPosts(@Query("q") String query, @Query("after") String after); + @GET("search.json?raw_json=1&type=link") + Call searchPosts(@Query("q") String query, @Query("after") String after, + @HeaderMap Map headers); - @GET("/r/{subredditName}/search.json?raw_json=1&restrict_sr=true") - Call searchPostsInSpecificSubreddit(@Query("q") String query, @Query("after") String after); + @GET("r/{subredditName}/search.json?raw_json=1&type=link&restrict_sr=true") + Call searchPostsInSpecificSubreddit(@Query("q") String query, @Query("after") String after, + @HeaderMap Map headers); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java index 51099a9a..a0e08f12 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java @@ -17,6 +17,7 @@ import androidx.viewpager.widget.ViewPager; public class SearchActivity extends AppCompatActivity { static final String QUERY_KEY = "QK"; + private String mQuery; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -36,6 +37,7 @@ public class SearchActivity extends AppCompatActivity { Intent intent = getIntent(); String query = intent.getExtras().getString(QUERY_KEY); if(query != null) { + mQuery = query; setTitle(query); } } @@ -58,13 +60,33 @@ public class SearchActivity extends AppCompatActivity { @Override public Fragment getItem(int position) { - // getItem is called to instantiate the fragment for the given page. - // Return a PlaceholderFragment (defined as a static inner class below). - PostFragment mFragment = new PostFragment(); - Bundle bundle = new Bundle(); - bundle.putInt(PostFragment.POST_TYPE_KEY, PostDataSource.TYPE_FRONT_PAGE); - mFragment.setArguments(bundle); - return mFragment; + switch (position) { + case 0: { + PostFragment mFragment = new PostFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(PostFragment.POST_TYPE_KEY, PostDataSource.TYPE_SEARCH); + bundle.putString(PostFragment.NAME_KEY, mQuery); + mFragment.setArguments(bundle); + return mFragment; + } + case 1: { + PostFragment mFragment = new PostFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(PostFragment.POST_TYPE_KEY, PostDataSource.TYPE_FRONT_PAGE); + bundle.putString(PostFragment.NAME_KEY, mQuery); + mFragment.setArguments(bundle); + return mFragment; + } + default: + { + PostFragment mFragment = new PostFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(PostFragment.POST_TYPE_KEY, PostDataSource.TYPE_FRONT_PAGE); + bundle.putString(PostFragment.NAME_KEY, mQuery); + mFragment.setArguments(bundle); + return mFragment; + } + } } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java index 86bd6c9b..df66d631 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java @@ -7,16 +7,6 @@ import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; -import androidx.annotation.Nullable; -import androidx.browser.customtabs.CustomTabsIntent; -import com.google.android.material.chip.Chip; -import androidx.coordinatorlayout.widget.CoordinatorLayout; -import com.google.android.material.snackbar.Snackbar; -import androidx.core.content.ContextCompat; -import androidx.appcompat.app.AppCompatActivity; -import androidx.cardview.widget.CardView; -import androidx.recyclerview.widget.DividerItemDecoration; -import androidx.recyclerview.widget.LinearLayoutManager; import android.view.MenuItem; import android.view.View; import android.widget.ImageView; @@ -34,6 +24,8 @@ import com.bumptech.glide.load.engine.GlideException; import com.bumptech.glide.request.RequestListener; import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.target.Target; +import com.google.android.material.chip.Chip; +import com.google.android.material.snackbar.Snackbar; import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar; import com.multilevelview.MultiLevelRecyclerView; import com.santalu.aspectratioimageview.AspectRatioImageView; @@ -46,6 +38,14 @@ import javax.inject.Named; import CustomView.AspectRatioGifImageView; import SubredditDatabase.SubredditRoomDatabase; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.browser.customtabs.CustomTabsIntent; +import androidx.cardview.widget.CardView; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; import butterknife.BindView; import butterknife.ButterKnife; import jp.wasabeef.glide.transformations.BlurTransformation;