package ml.docilealligator.infinityforreddit.Post; import androidx.annotation.NonNull; import androidx.lifecycle.MutableLiveData; import androidx.paging.PageKeyedDataSource; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import ml.docilealligator.infinityforreddit.NetworkState; import ml.docilealligator.infinityforreddit.API.RedditAPI; import ml.docilealligator.infinityforreddit.SortType; import ml.docilealligator.infinityforreddit.Utils.APIUtils; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Retrofit; public class PostDataSource extends PageKeyedDataSource<String, Post> { public static final int TYPE_FRONT_PAGE = 0; public static final int TYPE_SUBREDDIT = 1; public static final int TYPE_USER = 2; public static final int TYPE_SEARCH = 3; public static final int TYPE_MULTI_REDDIT = 4; public static final String USER_WHERE_SUBMITTED = "submitted"; public static final String USER_WHERE_UPVOTED = "upvoted"; public static final String USER_WHERE_DOWNVOTED = "downvoted"; public static final String USER_WHERE_HIDDEN = "hidden"; public static final String USER_WHERE_SAVED = "saved"; public static final String USER_WHERE_GILDED = "gilded"; private Retrofit retrofit; private String accessToken; private Locale locale; private String subredditOrUserName; private String query; private int postType; private SortType sortType; private boolean nsfw; private int filter; private String userWhere; private String multiRedditPath; private LinkedHashSet<Post> postLinkedHashSet; private MutableLiveData<NetworkState> paginationNetworkStateLiveData; private MutableLiveData<NetworkState> initialLoadStateLiveData; private MutableLiveData<Boolean> hasPostLiveData; private LoadParams<String> params; private LoadCallback<String, Post> callback; PostDataSource(Retrofit retrofit, String accessToken, Locale locale, int postType, SortType sortType, int filter, boolean nsfw) { this.retrofit = retrofit; this.accessToken = accessToken; this.locale = locale; paginationNetworkStateLiveData = new MutableLiveData<>(); initialLoadStateLiveData = new MutableLiveData<>(); hasPostLiveData = new MutableLiveData<>(); this.postType = postType; this.sortType = sortType == null ? new SortType(SortType.Type.BEST) : sortType; this.filter = filter; this.nsfw = nsfw; postLinkedHashSet = new LinkedHashSet<>(); } PostDataSource(Retrofit retrofit, String accessToken, Locale locale, String path, int postType, SortType sortType, int filter, boolean nsfw) { this.retrofit = retrofit; this.accessToken = accessToken; this.locale = locale; if (postType == TYPE_SUBREDDIT) { this.subredditOrUserName = path; } else { if (sortType != null) { if (path.endsWith("/")) { multiRedditPath = path + sortType.getType().value; } else { multiRedditPath = path + "/" + sortType.getType().value; } } else { multiRedditPath = path; } } paginationNetworkStateLiveData = new MutableLiveData<>(); initialLoadStateLiveData = new MutableLiveData<>(); hasPostLiveData = new MutableLiveData<>(); this.postType = postType; if (sortType == null) { if (path.equals("popular") || path.equals("all")) { this.sortType = new SortType(SortType.Type.HOT); } else { this.sortType = new SortType(SortType.Type.BEST); } } else { this.sortType = sortType; } this.filter = filter; this.nsfw = nsfw; postLinkedHashSet = new LinkedHashSet<>(); } PostDataSource(Retrofit retrofit, String accessToken, Locale locale, String subredditOrUserName, int postType, SortType sortType, String where, int filter, boolean nsfw) { this.retrofit = retrofit; this.accessToken = accessToken; this.locale = locale; this.subredditOrUserName = subredditOrUserName; paginationNetworkStateLiveData = new MutableLiveData<>(); initialLoadStateLiveData = new MutableLiveData<>(); hasPostLiveData = new MutableLiveData<>(); this.postType = postType; this.sortType = sortType == null ? new SortType(SortType.Type.NEW) : sortType; userWhere = where; this.filter = filter; this.nsfw = nsfw; postLinkedHashSet = new LinkedHashSet<>(); } PostDataSource(Retrofit retrofit, String accessToken, Locale locale, String subredditOrUserName, String query, int postType, SortType sortType, int filter, boolean nsfw) { this.retrofit = retrofit; this.accessToken = accessToken; this.locale = locale; this.subredditOrUserName = subredditOrUserName; this.query = query; paginationNetworkStateLiveData = new MutableLiveData<>(); initialLoadStateLiveData = new MutableLiveData<>(); hasPostLiveData = new MutableLiveData<>(); this.postType = postType; this.sortType = sortType == null ? new SortType(SortType.Type.RELEVANCE) : sortType; this.filter = filter; this.nsfw = nsfw; postLinkedHashSet = new LinkedHashSet<>(); } MutableLiveData<NetworkState> getPaginationNetworkStateLiveData() { return paginationNetworkStateLiveData; } MutableLiveData<NetworkState> getInitialLoadStateLiveData() { return initialLoadStateLiveData; } MutableLiveData<Boolean> hasPostLiveData() { return hasPostLiveData; } @Override public void loadInitial(@NonNull LoadInitialParams<String> params, @NonNull final LoadInitialCallback<String, Post> callback) { initialLoadStateLiveData.postValue(NetworkState.LOADING); switch (postType) { case TYPE_FRONT_PAGE: loadBestPostsInitial(callback, null); break; case TYPE_SUBREDDIT: loadSubredditPostsInitial(callback, null); break; case TYPE_USER: loadUserPostsInitial(callback, null); break; case TYPE_SEARCH: loadSearchPostsInitial(callback, null); break; case TYPE_MULTI_REDDIT: loadMultiRedditPostsInitial(callback, null); break; } } @Override public void loadBefore(@NonNull LoadParams<String> params, @NonNull LoadCallback<String, Post> callback) { } @Override public void loadAfter(@NonNull LoadParams<String> params, @NonNull final LoadCallback<String, Post> callback) { this.params = params; this.callback = callback; if (params == null || "".equals(params.key) || "null".equals(params.key)) { return; } paginationNetworkStateLiveData.postValue(NetworkState.LOADING); switch (postType) { case TYPE_FRONT_PAGE: loadBestPostsAfter(params, callback, null); break; case TYPE_SUBREDDIT: loadSubredditPostsAfter(params, callback, null); break; case TYPE_USER: loadUserPostsAfter(params, callback, null); break; case TYPE_SEARCH: loadSearchPostsAfter(params, callback, null); break; case TYPE_MULTI_REDDIT: loadMultiRedditPostsAfter(params, callback, null); break; } } private void loadBestPostsInitial(@NonNull final LoadInitialCallback<String, Post> callback, String lastItem) { RedditAPI api = retrofit.create(RedditAPI.class); Call<String> bestPost; if(sortType.getTime() != null) { bestPost = api.getBestPosts(sortType.getType().value, sortType.getTime().value, lastItem, APIUtils.getOAuthHeader(accessToken)); } else { bestPost = api.getBestPosts(sortType.getType().value, lastItem, APIUtils.getOAuthHeader(accessToken)); } bestPost.enqueue(new Callback<String>() { @Override public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) { if (response.isSuccessful()) { if (sortType.getType().value.equals(SortType.Type.RANDOM.value)) { ParsePost.parsePost(response.body(), locale, new ParsePost.ParsePostListener() { @Override public void onParsePostSuccess(Post post) { ArrayList<Post> singlePostList = new ArrayList<>(); singlePostList.add(post); callback.onResult(singlePostList, null, null); hasPostLiveData.postValue(true); initialLoadStateLiveData.postValue(NetworkState.LOADED); } @Override public void onParsePostFail() { initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); } }); } else { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override public void onParsePostsListingSuccess(LinkedHashSet<Post> newPosts, String lastItem) { String nextPageKey; if (lastItem == null || lastItem.equals("") || lastItem.equals("null")) { nextPageKey = null; } else { nextPageKey = lastItem; } if (newPosts.size() != 0) { postLinkedHashSet.addAll(newPosts); callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(true); } else if (nextPageKey != null) { loadBestPostsInitial(callback, nextPageKey); return; } else { postLinkedHashSet.addAll(newPosts); callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(false); } initialLoadStateLiveData.postValue(NetworkState.LOADED); } @Override public void onParsePostsListingFail() { initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing posts")); } }); } } else { initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "code: " + response.code() + " message: " + response.message())); } } @Override public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { String errorMessage = t.getMessage(); initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage + " " + call.request().url().toString())); } }); } private void loadBestPostsAfter(@NonNull LoadParams<String> params, @NonNull final LoadCallback<String, Post> callback, String lastItem) { String after = lastItem == null ? params.key : lastItem; RedditAPI api = retrofit.create(RedditAPI.class); Call<String> bestPost; if(sortType.getTime() != null) { bestPost = api.getBestPosts(sortType.getType().value, sortType.getTime().value, after, APIUtils.getOAuthHeader(accessToken)); } else { bestPost = api.getBestPosts(sortType.getType().value, after, APIUtils.getOAuthHeader(accessToken)); } bestPost.enqueue(new Callback<String>() { @Override public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) { if (response.isSuccessful()) { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override public void onParsePostsListingSuccess(LinkedHashSet<Post> newPosts, String lastItem) { if (newPosts.size() == 0 && lastItem != null && !lastItem.equals("") && !lastItem.equals("null")) { loadBestPostsAfter(params, callback, lastItem); } else { int currentPostsSize = postLinkedHashSet.size(); postLinkedHashSet.addAll(newPosts); if (currentPostsSize == postLinkedHashSet.size()) { callback.onResult(new ArrayList<>(), lastItem); } else { List<Post> newPostsList = new ArrayList<>(postLinkedHashSet).subList(currentPostsSize, postLinkedHashSet.size()); callback.onResult(newPostsList, lastItem); } paginationNetworkStateLiveData.postValue(NetworkState.LOADED); } } @Override public void onParsePostsListingFail() { paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing more posts")); } }); } else { paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, response.message())); } } @Override public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { String errorMessage = t.getMessage(); paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage)); } }); } private void loadSubredditPostsInitial(@NonNull final LoadInitialCallback<String, Post> callback, String lastItem) { RedditAPI api = retrofit.create(RedditAPI.class); Call<String> getPost; if (accessToken == null) { if (sortType.getTime() != null) { getPost = api.getSubredditBestPosts(subredditOrUserName, sortType.getType().value, sortType.getTime().value, lastItem); } else { getPost = api.getSubredditBestPosts(subredditOrUserName, sortType.getType().value, lastItem); } } else { if (sortType.getTime() != null) { getPost = api.getSubredditBestPostsOauth(subredditOrUserName, sortType.getType().value, sortType.getTime().value, lastItem, APIUtils.getOAuthHeader(accessToken)); } else { getPost = api.getSubredditBestPostsOauth(subredditOrUserName, sortType.getType().value, lastItem, APIUtils.getOAuthHeader(accessToken)); } } getPost.enqueue(new Callback<String>() { @Override public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) { if (response.isSuccessful()) { if (sortType.getType().value.equals(SortType.Type.RANDOM.value)) { ParsePost.parsePost(response.body(), locale, new ParsePost.ParsePostListener() { @Override public void onParsePostSuccess(Post post) { ArrayList<Post> singlePostList = new ArrayList<>(); singlePostList.add(post); callback.onResult(singlePostList, null, null); hasPostLiveData.postValue(true); initialLoadStateLiveData.postValue(NetworkState.LOADED); } @Override public void onParsePostFail() { initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); } }); } else { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override public void onParsePostsListingSuccess(LinkedHashSet<Post> newPosts, String lastItem) { String nextPageKey; if (lastItem == null || lastItem.equals("") || lastItem.equals("null")) { nextPageKey = null; } else { nextPageKey = lastItem; } if (newPosts.size() != 0) { postLinkedHashSet.addAll(newPosts); callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(true); } else if (nextPageKey != null) { loadSubredditPostsInitial(callback, nextPageKey); return; } else { postLinkedHashSet.addAll(newPosts); callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(false); } initialLoadStateLiveData.postValue(NetworkState.LOADED); } @Override public void onParsePostsListingFail() { initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing posts")); } }); } } else { initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "code: " + response + " message: " + response.message())); } } @Override public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { String errorMessage = t.getMessage(); initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage + " " + call.request().url().toString())); } }); } private void loadSubredditPostsAfter(@NonNull LoadParams<String> params, @NonNull final LoadCallback<String, Post> callback, String lastItem) { String after = lastItem == null ? params.key : lastItem; RedditAPI api = retrofit.create(RedditAPI.class); Call<String> getPost; if (accessToken == null) { if (sortType.getTime() != null) { getPost = api.getSubredditBestPosts(subredditOrUserName, sortType.getType().value, sortType.getTime().value, after); } else { getPost = api.getSubredditBestPosts(subredditOrUserName, sortType.getType().value, after); } } else { if (sortType.getTime() != null) { getPost = api.getSubredditBestPostsOauth(subredditOrUserName, sortType.getType().value, sortType.getTime().value, after, APIUtils.getOAuthHeader(accessToken)); } else { getPost = api.getSubredditBestPostsOauth(subredditOrUserName, sortType.getType().value, after, APIUtils.getOAuthHeader(accessToken)); } } getPost.enqueue(new Callback<String>() { @Override public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) { if (response.isSuccessful()) { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override public void onParsePostsListingSuccess(LinkedHashSet<Post> newPosts, String lastItem) { if (newPosts.size() == 0 && lastItem != null && !lastItem.equals("") && !lastItem.equals("null")) { loadSubredditPostsAfter(params, callback, lastItem); } else { int currentPostsSize = postLinkedHashSet.size(); postLinkedHashSet.addAll(newPosts); if (currentPostsSize == postLinkedHashSet.size()) { callback.onResult(new ArrayList<>(), lastItem); } else { List<Post> newPostsList = new ArrayList<>(postLinkedHashSet).subList(currentPostsSize, postLinkedHashSet.size()); callback.onResult(newPostsList, lastItem); } paginationNetworkStateLiveData.postValue(NetworkState.LOADED); } } @Override public void onParsePostsListingFail() { paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); } }); } else { paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, response.message())); } } @Override public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { String errorMessage = t.getMessage(); paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage)); } }); } private void loadUserPostsInitial(@NonNull final LoadInitialCallback<String, Post> callback, String lastItem) { RedditAPI api = retrofit.create(RedditAPI.class); Call<String> getPost; if (accessToken == null) { if (sortType.getTime() != null) { getPost = api.getUserPosts(subredditOrUserName, lastItem, sortType.getType().value, sortType.getTime().value); } else { getPost = api.getUserPosts(subredditOrUserName, lastItem, sortType.getType().value); } } else { if (sortType.getTime() != null) { getPost = api.getUserPostsOauth(subredditOrUserName, userWhere, lastItem, sortType.getType().value, sortType.getTime().value, APIUtils.getOAuthHeader(accessToken)); } else { getPost = api.getUserPostsOauth(subredditOrUserName, userWhere, lastItem, sortType.getType().value, APIUtils.getOAuthHeader(accessToken)); } } getPost.enqueue(new Callback<String>() { @Override public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) { if (response.isSuccessful()) { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override public void onParsePostsListingSuccess(LinkedHashSet<Post> newPosts, String lastItem) { String nextPageKey; if (lastItem == null || lastItem.equals("") || lastItem.equals("null")) { nextPageKey = null; } else { nextPageKey = lastItem; } if (newPosts.size() != 0) { postLinkedHashSet.addAll(newPosts); callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(true); } else if (nextPageKey != null) { loadUserPostsInitial(callback, nextPageKey); return; } else { postLinkedHashSet.addAll(newPosts); callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(false); } initialLoadStateLiveData.postValue(NetworkState.LOADED); } @Override public void onParsePostsListingFail() { initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); } }); } else { initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, response.message())); } } @Override public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { String errorMessage = t.getMessage(); initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage)); } }); } private void loadUserPostsAfter(@NonNull LoadParams<String> params, @NonNull final LoadCallback<String, Post> callback, String lastItem) { String after = lastItem == null ? params.key : lastItem; RedditAPI api = retrofit.create(RedditAPI.class); Call<String> getPost; if (accessToken == null) { if (sortType.getTime() != null) { getPost = api.getUserPosts(subredditOrUserName, after, sortType.getType().value, sortType.getTime().value); } else { getPost = api.getUserPosts(subredditOrUserName, after, sortType.getType().value); } } else { if (sortType.getTime() != null) { getPost = api.getUserPostsOauth(subredditOrUserName, userWhere, after, sortType.getType().value, sortType.getTime().value, APIUtils.getOAuthHeader(accessToken)); } else { getPost = api.getUserPostsOauth(subredditOrUserName, userWhere, after, sortType.getType().value, APIUtils.getOAuthHeader(accessToken)); } } getPost.enqueue(new Callback<String>() { @Override public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) { if (response.isSuccessful()) { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override public void onParsePostsListingSuccess(LinkedHashSet<Post> newPosts, String lastItem) { if (newPosts.size() == 0 && lastItem != null && !lastItem.equals("") && !lastItem.equals("null")) { loadUserPostsAfter(params, callback, lastItem); } else { int currentPostsSize = postLinkedHashSet.size(); postLinkedHashSet.addAll(newPosts); if (currentPostsSize == postLinkedHashSet.size()) { callback.onResult(new ArrayList<>(), lastItem); } else { List<Post> newPostsList = new ArrayList<>(postLinkedHashSet).subList(currentPostsSize, postLinkedHashSet.size()); callback.onResult(newPostsList, lastItem); } paginationNetworkStateLiveData.postValue(NetworkState.LOADED); } } @Override public void onParsePostsListingFail() { paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); } }); } else { paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, response.message())); } } @Override public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { String errorMessage = t.getMessage(); paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage)); } }); } private void loadSearchPostsInitial(@NonNull final LoadInitialCallback<String, Post> callback, String lastItem) { RedditAPI api = retrofit.create(RedditAPI.class); Call<String> getPost; if (subredditOrUserName == null) { if (accessToken == null) { if (sortType.getTime() != null) { getPost = api.searchPosts(query, lastItem, sortType.getType().value, sortType.getTime().value); } else { getPost = api.searchPosts(query, lastItem, sortType.getType().value); } } else { if(sortType.getTime() != null) { getPost = api.searchPostsOauth(query, lastItem, sortType.getType().value, sortType.getTime().value, APIUtils.getOAuthHeader(accessToken)); } else { getPost = api.searchPostsOauth(query, lastItem, sortType.getType().value, APIUtils.getOAuthHeader(accessToken)); } } } else { if (accessToken == null) { if (sortType.getTime() != null) { getPost = api.searchPostsInSpecificSubreddit(subredditOrUserName, query, sortType.getType().value, sortType.getTime().value, lastItem); } else { getPost = api.searchPostsInSpecificSubreddit(subredditOrUserName, query, sortType.getType().value, lastItem); } } else { if (sortType.getTime() != null) { getPost = api.searchPostsInSpecificSubredditOauth(subredditOrUserName, query, sortType.getType().value, sortType.getTime().value, lastItem, APIUtils.getOAuthHeader(accessToken)); } else { getPost = api.searchPostsInSpecificSubredditOauth(subredditOrUserName, query, sortType.getType().value, lastItem, APIUtils.getOAuthHeader(accessToken)); } } } getPost.enqueue(new Callback<String>() { @Override public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) { if (response.isSuccessful()) { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override public void onParsePostsListingSuccess(LinkedHashSet<Post> newPosts, String lastItem) { String nextPageKey; if (lastItem == null || lastItem.equals("") || lastItem.equals("null")) { nextPageKey = null; } else { nextPageKey = lastItem; } if (newPosts.size() != 0) { postLinkedHashSet.addAll(newPosts); callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(true); } else if (nextPageKey != null) { loadSearchPostsInitial(callback, nextPageKey); return; } else { postLinkedHashSet.addAll(newPosts); callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(false); } initialLoadStateLiveData.postValue(NetworkState.LOADED); } @Override public void onParsePostsListingFail() { initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); } }); } else { initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, response.message())); } } @Override public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { String errorMessage = t.getMessage(); initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage)); } }); } private void loadSearchPostsAfter(@NonNull LoadParams<String> params, @NonNull final LoadCallback<String, Post> callback, String lastItem) { String after = lastItem == null ? params.key : lastItem; RedditAPI api = retrofit.create(RedditAPI.class); Call<String> getPost; if (subredditOrUserName == null) { if (accessToken == null) { if (sortType.getTime() != null) { getPost = api.searchPosts(query, after, sortType.getType().value, sortType.getTime().value); } else { getPost = api.searchPosts(query, after, sortType.getType().value); } } else { if (sortType.getTime() != null) { getPost = api.searchPostsOauth(query, after, sortType.getType().value, sortType.getTime().value, APIUtils.getOAuthHeader(accessToken)); } else { getPost = api.searchPostsOauth(query, after, sortType.getType().value, APIUtils.getOAuthHeader(accessToken)); } } } else { if (accessToken == null) { if (sortType.getTime() != null) { getPost = api.searchPostsInSpecificSubreddit(subredditOrUserName, query, sortType.getType().value, sortType.getTime().value, after); } else { getPost = api.searchPostsInSpecificSubreddit(subredditOrUserName, query, sortType.getType().value, after); } } else { if (sortType.getTime() != null) { getPost = api.searchPostsInSpecificSubredditOauth(subredditOrUserName, query, sortType.getType().value, sortType.getTime().value, after, APIUtils.getOAuthHeader(accessToken)); } else { getPost = api.searchPostsInSpecificSubredditOauth(subredditOrUserName, query, sortType.getType().value, after, APIUtils.getOAuthHeader(accessToken)); } } } getPost.enqueue(new Callback<String>() { @Override public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) { if (response.isSuccessful()) { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override public void onParsePostsListingSuccess(LinkedHashSet<Post> newPosts, String lastItem) { if (newPosts.size() == 0 && lastItem != null && !lastItem.equals("") && !lastItem.equals("null")) { loadSearchPostsAfter(params, callback, lastItem); } else { int currentPostsSize = postLinkedHashSet.size(); postLinkedHashSet.addAll(newPosts); if (currentPostsSize == postLinkedHashSet.size()) { callback.onResult(new ArrayList<>(), lastItem); } else { List<Post> newPostsList = new ArrayList<>(postLinkedHashSet).subList(currentPostsSize, postLinkedHashSet.size()); callback.onResult(newPostsList, lastItem); } paginationNetworkStateLiveData.postValue(NetworkState.LOADED); } } @Override public void onParsePostsListingFail() { paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); } }); } else { paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, response.message())); } } @Override public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { String errorMessage = t.getMessage(); paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage)); } }); } private void loadMultiRedditPostsInitial(@NonNull final LoadInitialCallback<String, Post> callback, String lastItem) { RedditAPI api = retrofit.create(RedditAPI.class); Call<String> getPost; if (accessToken == null) { if (sortType.getTime() != null) { getPost = api.getMultiRedditPosts(multiRedditPath, lastItem, sortType.getTime().value); } else { getPost = api.getMultiRedditPosts(multiRedditPath, lastItem); } } else { if (sortType.getTime() != null) { getPost = api.getMultiRedditPostsOauth(multiRedditPath, lastItem, sortType.getTime().value, APIUtils.getOAuthHeader(accessToken)); } else { getPost = api.getMultiRedditPostsOauth(multiRedditPath, lastItem, APIUtils.getOAuthHeader(accessToken)); } } getPost.enqueue(new Callback<String>() { @Override public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) { if (response.isSuccessful()) { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override public void onParsePostsListingSuccess(LinkedHashSet<Post> newPosts, String lastItem) { String nextPageKey; if (lastItem == null || lastItem.equals("") || lastItem.equals("null")) { nextPageKey = null; } else { nextPageKey = lastItem; } if (newPosts.size() != 0) { postLinkedHashSet.addAll(newPosts); callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(true); } else if (nextPageKey != null) { loadMultiRedditPostsInitial(callback, nextPageKey); return; } else { postLinkedHashSet.addAll(newPosts); callback.onResult(new ArrayList<>(newPosts), null, nextPageKey); hasPostLiveData.postValue(false); } initialLoadStateLiveData.postValue(NetworkState.LOADED); } @Override public void onParsePostsListingFail() { initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); } }); } else { initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, response.message())); } } @Override public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { String errorMessage = t.getMessage(); initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage)); } }); } private void loadMultiRedditPostsAfter(@NonNull LoadParams<String> params, @NonNull final LoadCallback<String, Post> callback, String lastItem) { String after = lastItem == null ? params.key : lastItem; RedditAPI api = retrofit.create(RedditAPI.class); Call<String> getPost; if (accessToken == null) { if (sortType.getTime() != null) { getPost = api.getMultiRedditPosts(multiRedditPath, after, sortType.getTime().value); } else { getPost = api.getMultiRedditPosts(multiRedditPath, after); } } else { if (sortType.getTime() != null) { getPost = api.getMultiRedditPostsOauth(multiRedditPath, after, sortType.getTime().value, APIUtils.getOAuthHeader(accessToken)); } else { getPost = api.getMultiRedditPostsOauth(multiRedditPath, after, APIUtils.getOAuthHeader(accessToken)); } } getPost.enqueue(new Callback<String>() { @Override public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) { if (response.isSuccessful()) { ParsePost.parsePosts(response.body(), locale, -1, filter, nsfw, new ParsePost.ParsePostsListingListener() { @Override public void onParsePostsListingSuccess(LinkedHashSet<Post> newPosts, String lastItem) { if (newPosts.size() == 0 && lastItem != null && !lastItem.equals("") && !lastItem.equals("null")) { loadMultiRedditPostsAfter(params, callback, lastItem); } else { int currentPostsSize = postLinkedHashSet.size(); postLinkedHashSet.addAll(newPosts); if (currentPostsSize == postLinkedHashSet.size()) { callback.onResult(new ArrayList<>(), lastItem); } else { List<Post> newPostsList = new ArrayList<>(postLinkedHashSet).subList(currentPostsSize, postLinkedHashSet.size()); callback.onResult(newPostsList, lastItem); } paginationNetworkStateLiveData.postValue(NetworkState.LOADED); } } @Override public void onParsePostsListingFail() { paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data")); } }); } else { paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, response.message())); } } @Override public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { String errorMessage = t.getMessage(); paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage)); } }); } void retryLoadingMore() { loadAfter(params, callback); } }