aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.idea/caches/build_file_checksums.serbin533 -> 533 bytes
-rw-r--r--.idea/caches/gradle_models.serbin303289 -> 303289 bytes
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/CheckIsSubscribedToSubredditAsyncTask.java42
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubredditData.java59
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/InsertSubscribedThingsAsyncTask.java72
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java61
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/NetworkComponent.java1
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubredditData.java104
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java26
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/PostViewModel.java12
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java3
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java5
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingDataSource.java107
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingDataSourceFactory.java40
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingFragment.java141
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingRecyclerViewAdapter.java233
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingViewModel.java79
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/SubredditSubscription.java10
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java33
-rw-r--r--app/src/main/res/layout/fragment_subreddit_listing.xml47
-rw-r--r--app/src/main/res/layout/item_footer_error.xml8
-rw-r--r--app/src/main/res/layout/item_subreddit_listing.xml48
-rw-r--r--app/src/main/res/values/strings.xml9
24 files changed, 1026 insertions, 116 deletions
diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser
index 9f603d1b..401fbdb5 100644
--- a/.idea/caches/build_file_checksums.ser
+++ b/.idea/caches/build_file_checksums.ser
Binary files differ
diff --git a/.idea/caches/gradle_models.ser b/.idea/caches/gradle_models.ser
index 64b76d98..51f7172a 100644
--- a/.idea/caches/gradle_models.ser
+++ b/.idea/caches/gradle_models.ser
Binary files differ
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CheckIsSubscribedToSubredditAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CheckIsSubscribedToSubredditAsyncTask.java
new file mode 100644
index 00000000..d1cf3cf1
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CheckIsSubscribedToSubredditAsyncTask.java
@@ -0,0 +1,42 @@
+package ml.docilealligator.infinityforreddit;
+
+import android.os.AsyncTask;
+
+import SubscribedSubredditDatabase.SubscribedSubredditDao;
+import SubscribedSubredditDatabase.SubscribedSubredditData;
+
+class CheckIsSubscribedToSubredditAsyncTask extends AsyncTask<Void, Void, Void> {
+
+ private SubscribedSubredditDao subscribedSubredditDao;
+ private String subredditName;
+ private SubscribedSubredditData subscribedSubredditData;
+ private CheckIsSubscribedToSubredditListener checkIsSubscribedToSubredditListener;
+
+ interface CheckIsSubscribedToSubredditListener {
+ void isSubscribed();
+ void isNotSubscribed();
+ }
+
+ CheckIsSubscribedToSubredditAsyncTask(SubscribedSubredditDao subscribedSubredditDao, String subredditName,
+ CheckIsSubscribedToSubredditListener checkIsSubscribedToSubredditListener) {
+ this.subscribedSubredditDao = subscribedSubredditDao;
+ this.subredditName =subredditName;
+ this.checkIsSubscribedToSubredditListener = checkIsSubscribedToSubredditListener;
+ }
+
+ @Override
+ protected Void doInBackground(Void... voids) {
+ subscribedSubredditData = subscribedSubredditDao.getSubscribedSubreddit(subredditName);
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ super.onPostExecute(aVoid);
+ if(subscribedSubredditData != null) {
+ checkIsSubscribedToSubredditListener.isSubscribed();
+ } else {
+ checkIsSubscribedToSubredditListener.isNotSubscribed();
+ }
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubredditData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubredditData.java
index f3f1536b..b7c5a73e 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubredditData.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchSubredditData.java
@@ -1,8 +1,11 @@
package ml.docilealligator.infinityforreddit;
-import androidx.annotation.NonNull;
import android.util.Log;
+import java.util.ArrayList;
+
+import SubredditDatabase.SubredditData;
+import androidx.annotation.NonNull;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@@ -10,10 +13,15 @@ import retrofit2.Retrofit;
class FetchSubredditData {
interface FetchSubredditDataListener {
- void onFetchSubredditDataSuccess(String response);
+ void onFetchSubredditDataSuccess(SubredditData subredditData, int nCurrentOnlineSubscribers);
void onFetchSubredditDataFail();
}
+ interface FetchSubredditListingDataListener {
+ void onFetchSubredditListingDataSuccess(ArrayList<SubredditData> subredditData, String after);
+ void onFetchSubredditListingDataFail();
+ }
+
static void fetchSubredditData(Retrofit retrofit, String subredditName, final FetchSubredditDataListener fetchSubredditDataListener) {
RedditAPI api = retrofit.create(RedditAPI.class);
@@ -22,7 +30,18 @@ class FetchSubredditData {
@Override
public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
if(response.isSuccessful()) {
- fetchSubredditDataListener.onFetchSubredditDataSuccess(response.body());
+ ParseSubredditData.parseSubredditData(response.body(), new ParseSubredditData.ParseSubredditDataListener() {
+ @Override
+ public void onParseSubredditDataSuccess(SubredditData subredditData, int nCurrentOnlineSubscribers) {
+ fetchSubredditDataListener.onFetchSubredditDataSuccess(subredditData, nCurrentOnlineSubscribers);
+ }
+
+ @Override
+ public void onParseSubredditDataFail() {
+ Log.i("parse failed", "true");
+ fetchSubredditDataListener.onFetchSubredditDataFail();
+ }
+ });
} else {
Log.i("call failed", response.message());
fetchSubredditDataListener.onFetchSubredditDataFail();
@@ -36,4 +55,38 @@ class FetchSubredditData {
}
});
}
+
+ static void fetchSubredditListingData(Retrofit retrofit, String query, String after, final FetchSubredditListingDataListener fetchSubredditListingDataListener) {
+ RedditAPI api = retrofit.create(RedditAPI.class);
+
+ Call<String> subredditDataCall = api.searchSubreddits(query, after);
+ subredditDataCall.enqueue(new Callback<String>() {
+ @Override
+ public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
+ if(response.isSuccessful()) {
+ ParseSubredditData.parseSubredditListingData(response.body(), new ParseSubredditData.ParseSubredditListingDataListener() {
+ @Override
+ public void onParseSubredditListingDataSuccess(ArrayList<SubredditData> subredditData, String after) {
+ fetchSubredditListingDataListener.onFetchSubredditListingDataSuccess(subredditData, after);
+ }
+
+ @Override
+ public void onParseSubredditListingDataFail() {
+ Log.i("parse failed", "true");
+ fetchSubredditListingDataListener.onFetchSubredditListingDataFail();
+ }
+ });
+ } else {
+ Log.i("call failed", response.message());
+ fetchSubredditListingDataListener.onFetchSubredditListingDataFail();
+ }
+ }
+
+ @Override
+ public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
+ Log.i("call failed", t.getMessage());
+ fetchSubredditListingDataListener.onFetchSubredditListingDataFail();
+ }
+ });
+ }
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/InsertSubscribedThingsAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/InsertSubscribedThingsAsyncTask.java
new file mode 100644
index 00000000..c5b517c2
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/InsertSubscribedThingsAsyncTask.java
@@ -0,0 +1,72 @@
+package ml.docilealligator.infinityforreddit;
+
+import android.os.AsyncTask;
+
+import java.util.List;
+
+import SubredditDatabase.SubredditDao;
+import SubredditDatabase.SubredditData;
+import SubscribedSubredditDatabase.SubscribedSubredditDao;
+import SubscribedSubredditDatabase.SubscribedSubredditData;
+import SubscribedUserDatabase.SubscribedUserDao;
+import SubscribedUserDatabase.SubscribedUserData;
+
+class InsertSubscribedThingsAsyncTask extends AsyncTask<Void, Void, Void> {
+
+ interface InsertSubscribedThingListener {
+ void insertSuccess();
+ }
+
+ private SubscribedSubredditDao mSubscribedSubredditDao;
+ private SubscribedUserDao mUserDao;
+ private SubredditDao mSubredditDao;
+ private List<SubscribedSubredditData> subscribedSubredditData;
+ private List<SubscribedUserData> subscribedUserData;
+ private List<SubredditData> subredditData;
+ private InsertSubscribedThingListener insertSubscribedThingListener;
+
+ InsertSubscribedThingsAsyncTask(SubscribedSubredditDao subscribedSubredditDao,
+ SubscribedUserDao userDao,
+ SubredditDao subredditDao,
+ List<SubscribedSubredditData> subscribedSubredditData,
+ List<SubscribedUserData> subscribedUserData,
+ List<SubredditData> subredditData,
+ InsertSubscribedThingListener insertSubscribedThingListener) {
+
+ mSubscribedSubredditDao = subscribedSubredditDao;
+ mUserDao = userDao;
+ mSubredditDao = subredditDao;
+
+ this.subscribedSubredditData = subscribedSubredditData;
+ this.subscribedUserData = subscribedUserData;
+ this.subredditData = subredditData;
+ this.insertSubscribedThingListener = insertSubscribedThingListener;
+ }
+
+ @Override
+ protected Void doInBackground(final Void... params) {
+ if(subscribedSubredditData != null) {
+ for (SubscribedSubredditData s : subscribedSubredditData) {
+ mSubscribedSubredditDao.insert(s);
+ }
+ }
+
+ if(subscribedUserData != null) {
+ for (SubscribedUserData s : subscribedUserData) {
+ mUserDao.insert(s);
+ }
+ }
+
+ if(subredditData != null) {
+ for (SubredditData s : subredditData) {
+ mSubredditDao.insert(s);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ insertSubscribedThingListener.insertSuccess();
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java
index 46730021..7448daf9 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java
@@ -3,7 +3,6 @@ package ml.docilealligator.infinityforreddit;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
@@ -17,19 +16,15 @@ import com.bumptech.glide.RequestManager;
import com.ferfalk.simplesearchview.SimpleSearchView;
import java.util.ArrayList;
-import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
-import SubredditDatabase.SubredditDao;
import SubredditDatabase.SubredditData;
import SubredditDatabase.SubredditRoomDatabase;
-import SubscribedSubredditDatabase.SubscribedSubredditDao;
import SubscribedSubredditDatabase.SubscribedSubredditData;
import SubscribedSubredditDatabase.SubscribedSubredditRoomDatabase;
import SubscribedSubredditDatabase.SubscribedSubredditViewModel;
-import SubscribedUserDatabase.SubscribedUserDao;
import SubscribedUserDatabase.SubscribedUserData;
import SubscribedUserDatabase.SubscribedUserRoomDatabase;
import SubscribedUserDatabase.SubscribedUserViewModel;
@@ -295,9 +290,9 @@ public class MainActivity extends AppCompatActivity {
ArrayList<SubscribedUserData> subscribedUserData,
ArrayList<SubredditData> subredditData) {
new InsertSubscribedThingsAsyncTask(
- SubscribedSubredditRoomDatabase.getDatabase(MainActivity.this),
- SubscribedUserRoomDatabase.getDatabase(MainActivity.this),
- SubredditRoomDatabase.getDatabase(MainActivity.this),
+ SubscribedSubredditRoomDatabase.getDatabase(MainActivity.this).subscribedSubredditDao(),
+ SubscribedUserRoomDatabase.getDatabase(MainActivity.this).subscribedUserDao(),
+ SubredditRoomDatabase.getDatabase(MainActivity.this).subredditDao(),
subscribedSubredditData,
subscribedUserData,
subredditData,
@@ -391,54 +386,4 @@ public class MainActivity extends AppCompatActivity {
glide.load(mBannerImageUrl).into(mBannerImageView);
}
}
-
- private static class InsertSubscribedThingsAsyncTask extends AsyncTask<Void, Void, Void> {
-
- interface InsertSubscribedThingListener {
- void insertSuccess();
- }
-
- private final SubscribedSubredditDao mSubscribedSubredditDao;
- private final SubscribedUserDao mUserDao;
- private final SubredditDao mSubredditDao;
- private List<SubscribedSubredditData> subscribedSubredditData;
- private List<SubscribedUserData> subscribedUserData;
- private List<SubredditData> subredditData;
- private InsertSubscribedThingListener insertSubscribedThingListener;
-
- InsertSubscribedThingsAsyncTask(SubscribedSubredditRoomDatabase subscribedSubredditDb,
- SubscribedUserRoomDatabase userDb,
- SubredditRoomDatabase subredditDb,
- List<SubscribedSubredditData> subscribedSubredditData,
- List<SubscribedUserData> subscribedUserData,
- List<SubredditData> subredditData,
- InsertSubscribedThingListener insertSubscribedThingListener) {
- mSubscribedSubredditDao = subscribedSubredditDb.subscribedSubredditDao();
- mUserDao = userDb.subscribedUserDao();
- mSubredditDao = subredditDb.subredditDao();
- this.subscribedSubredditData = subscribedSubredditData;
- this.subscribedUserData = subscribedUserData;
- this.subredditData = subredditData;
- this.insertSubscribedThingListener = insertSubscribedThingListener;
- }
-
- @Override
- protected Void doInBackground(final Void... params) {
- for (SubscribedSubredditData s : subscribedSubredditData) {
- mSubscribedSubredditDao.insert(s);
- }
- for (SubscribedUserData s : subscribedUserData) {
- mUserDao.insert(s);
- }
- for (SubredditData s : subredditData) {
- mSubredditDao.insert(s);
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Void aVoid) {
- insertSubscribedThingListener.insertSuccess();
- }
- }
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkComponent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkComponent.java
index 747dead0..05aae8af 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkComponent.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkComponent.java
@@ -9,6 +9,7 @@ import dagger.Component;
interface NetworkComponent {
void inject(MainActivity mainActivity);
void inject(PostFragment postFragment);
+ void inject(SubredditListingFragment subredditListingFragment);
void inject(ViewPostDetailActivity viewPostDetailActivity);
void inject(ViewSubredditDetailActivity viewSubredditDetailActivity);
void inject(ViewUserDetailActivity viewUserDetailActivity);
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubredditData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubredditData.java
index cc7a0326..e12da13f 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubredditData.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubredditData.java
@@ -3,9 +3,12 @@ package ml.docilealligator.infinityforreddit;
import android.os.AsyncTask;
import android.util.Log;
+import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import java.util.ArrayList;
+
import SubredditDatabase.SubredditData;
class ParseSubredditData {
@@ -14,10 +17,19 @@ class ParseSubredditData {
void onParseSubredditDataFail();
}
+ interface ParseSubredditListingDataListener {
+ void onParseSubredditListingDataSuccess(ArrayList<SubredditData> subredditData, String after);
+ void onParseSubredditListingDataFail();
+ }
+
static void parseSubredditData(String response, ParseSubredditDataListener parseSubredditDataListener) {
new ParseSubredditDataAsyncTask(response, parseSubredditDataListener).execute();
}
+ static void parseSubredditListingData(String response, ParseSubredditListingDataListener parseSubredditListingDataListener) {
+ new ParseSubredditListingDataAsyncTask(response, parseSubredditListingDataListener).execute();
+ }
+
private static class ParseSubredditDataAsyncTask extends AsyncTask<Void, Void, Void> {
private JSONObject jsonResponse;
private boolean parseFailed;
@@ -31,7 +43,7 @@ class ParseSubredditData {
jsonResponse = new JSONObject(response);
parseFailed = false;
} catch (JSONException e) {
- Log.i("comment json error", e.getMessage());
+ Log.i("subreddit json error", e.getMessage());
parseSubredditDataListener.onParseSubredditDataFail();
}
}
@@ -40,7 +52,9 @@ class ParseSubredditData {
protected Void doInBackground(Void... voids) {
try {
JSONObject data = jsonResponse.getJSONObject(JSONUtils.DATA_KEY);
- String id = data.getString(JSONUtils.NAME_KEY);
+ mNCurrentOnlineSubscribers = data.getInt(JSONUtils.ACTIVE_USER_COUNT_KEY);
+ subredditData = parseSubredditData(data);
+ /*String id = data.getString(JSONUtils.NAME_KEY);
String subredditFullName = data.getString(JSONUtils.DISPLAY_NAME);
String description = data.getString(JSONUtils.PUBLIC_DESCRIPTION_KEY).trim();
@@ -67,7 +81,7 @@ class ParseSubredditData {
int nSubscribers = data.getInt(JSONUtils.SUBSCRIBERS_KEY);
int nCurrentOnlineSubscribers = data.getInt(JSONUtils.ACTIVE_USER_COUNT_KEY);
subredditData = new SubredditData(id, subredditFullName, iconUrl, bannerImageUrl, description, nSubscribers);
- mNCurrentOnlineSubscribers = nCurrentOnlineSubscribers;
+ mNCurrentOnlineSubscribers = nCurrentOnlineSubscribers;*/
} catch (JSONException e) {
parseFailed = true;
Log.i("parse", "SubredditData error");
@@ -85,4 +99,88 @@ class ParseSubredditData {
}
}
}
+
+ private static class ParseSubredditListingDataAsyncTask extends AsyncTask<Void, Void, Void> {
+ private JSONObject jsonResponse;
+ private boolean parseFailed;
+ private ParseSubredditListingDataListener parseSubredditListingDataListener;
+ private ArrayList<SubredditData> subredditListingData;
+ private String after;
+
+ ParseSubredditListingDataAsyncTask(String response, ParseSubredditListingDataListener parseSubredditListingDataListener){
+ this.parseSubredditListingDataListener = parseSubredditListingDataListener;
+ try {
+ jsonResponse = new JSONObject(response);
+ parseFailed = false;
+ subredditListingData = new ArrayList<>();
+ } catch (JSONException e) {
+ Log.i("subreddit json error", e.getMessage());
+ parseFailed = true;
+ parseSubredditListingDataListener.onParseSubredditListingDataFail();
+ }
+ }
+
+ @Override
+ protected Void doInBackground(Void... voids) {
+ try {
+ if(!parseFailed) {
+ JSONArray children = jsonResponse.getJSONObject(JSONUtils.DATA_KEY)
+ .getJSONArray(JSONUtils.CHILDREN_KEY);
+ for(int i = 0; i < children.length(); i++) {
+ JSONObject data = children.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY);
+ SubredditData subredditData = parseSubredditData(data);
+ subredditListingData.add(subredditData);
+ }
+ after = jsonResponse.getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.AFTER_KEY);
+ }
+ } catch (JSONException e) {
+ parseFailed = true;
+ Log.i("parse", "SubredditDataListing error");
+ parseSubredditListingDataListener.onParseSubredditListingDataFail();
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ if(!parseFailed) {
+ parseSubredditListingDataListener.onParseSubredditListingDataSuccess(subredditListingData, after);
+ } else {
+ parseSubredditListingDataListener.onParseSubredditListingDataFail();
+ }
+ }
+ }
+
+ private static SubredditData parseSubredditData(JSONObject subredditDataJsonObject) throws JSONException {
+ String id = subredditDataJsonObject.getString(JSONUtils.NAME_KEY);
+ String subredditFullName = subredditDataJsonObject.getString(JSONUtils.DISPLAY_NAME);
+ String description = subredditDataJsonObject.getString(JSONUtils.PUBLIC_DESCRIPTION_KEY).trim();
+
+ String bannerImageUrl;
+ if(subredditDataJsonObject.isNull(JSONUtils.BANNER_BACKGROUND_IMAGE_KEY)) {
+ bannerImageUrl = "";
+ } else {
+ bannerImageUrl = subredditDataJsonObject.getString(JSONUtils.BANNER_BACKGROUND_IMAGE_KEY);
+ }
+ if(bannerImageUrl.equals("") && !subredditDataJsonObject.isNull(JSONUtils.BANNER_IMG_KEY)) {
+ bannerImageUrl= subredditDataJsonObject.getString(JSONUtils.BANNER_IMG_KEY);
+ }
+
+ String iconUrl;
+ if(subredditDataJsonObject.isNull(JSONUtils.COMMUNITY_ICON_KEY)) {
+ iconUrl = "";
+ } else {
+ iconUrl = subredditDataJsonObject.getString(JSONUtils.COMMUNITY_ICON_KEY);
+ }
+ if(iconUrl.equals("") && !subredditDataJsonObject.isNull(JSONUtils.ICON_IMG_KEY)) {
+ iconUrl = subredditDataJsonObject.getString(JSONUtils.ICON_IMG_KEY);
+ }
+
+ int nSubscribers = 0;
+ if(!subredditDataJsonObject.isNull(JSONUtils.SUBSCRIBERS_KEY)) {
+ nSubscribers = subredditDataJsonObject.getInt(JSONUtils.SUBSCRIBERS_KEY);
+ }
+
+ return new SubredditData(id, subredditFullName, iconUrl, bannerImageUrl, description, nSubscribers);
+ }
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java
index c30991b3..7461bd21 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java
@@ -115,8 +115,10 @@ class PostDataSource extends PageKeyedDataSource<String, Post> {
break;
case TYPE_USER:
loadUserPostsAfter(params, callback);
+ break;
case TYPE_SEARCH:
loadSearchPostsAfter(params, callback);
+ break;
}
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java
index 657919ed..2a6330cb 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java
@@ -1,21 +1,11 @@
package ml.docilealligator.infinityforreddit;
-import androidx.paging.PagedListAdapter;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.ColorFilter;
import android.graphics.drawable.Drawable;
import android.net.Uri;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.browser.customtabs.CustomTabsIntent;
-import com.google.android.material.card.MaterialCardView;
-import com.google.android.material.chip.Chip;
-import androidx.core.content.ContextCompat;
-import androidx.recyclerview.widget.DiffUtil;
-import androidx.cardview.widget.CardView;
-import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -36,12 +26,22 @@ 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.card.MaterialCardView;
+import com.google.android.material.chip.Chip;
import CustomView.AspectRatioGifImageView;
import SubredditDatabase.SubredditDao;
import SubredditDatabase.SubredditRoomDatabase;
import User.UserDao;
import User.UserRoomDatabase;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.cardview.widget.CardView;
+import androidx.core.content.ContextCompat;
+import androidx.paging.PagedListAdapter;
+import androidx.recyclerview.widget.DiffUtil;
+import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import jp.wasabeef.glide.transformations.BlurTransformation;
@@ -600,12 +600,14 @@ class PostRecyclerViewAdapter extends PagedListAdapter<Post, RecyclerView.ViewHo
}
class ErrorViewHolder extends RecyclerView.ViewHolder {
- @BindView(R.id.relative_layout_footer_progress_bar_item) RelativeLayout relativeLayout;
- @BindView(R.id.retry_button_footer_progress_bar_item) Button retryButton;
+ @BindView(R.id.relative_layout_footer_error_item) RelativeLayout relativeLayout;
+ @BindView(R.id.error_text_view_footer_error_item) TextView errorTextView;
+ @BindView(R.id.retry_button_footer_error_item) Button retryButton;
ErrorViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
+ errorTextView.setText(R.string.load_posts_failed);
retryButton.setOnClickListener(view -> retryLoadingMoreCallback.retryLoadingMore());
}
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostViewModel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostViewModel.java
index 93d51f25..ab622d09 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostViewModel.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PostViewModel.java
@@ -1,15 +1,15 @@
package ml.docilealligator.infinityforreddit;
+import java.util.Locale;
+
+import androidx.annotation.NonNull;
+import androidx.arch.core.util.Function;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Transformations;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.paging.LivePagedListBuilder;
import androidx.paging.PagedList;
-import androidx.annotation.NonNull;
-
-import java.util.Locale;
-
import retrofit2.Retrofit;
public class PostViewModel extends ViewModel {
@@ -23,9 +23,9 @@ public class PostViewModel extends ViewModel {
postDataSourceFactory = new PostDataSourceFactory(retrofit, accessToken, locale, postType, onPostFetchedCallback);
initialLoadingState = Transformations.switchMap(postDataSourceFactory.getPostDataSourceLiveData(),
- dataSource -> dataSource.getInitialLoadStateLiveData());
+ (Function<PostDataSource, LiveData<NetworkState>>) PostDataSource::getInitialLoadStateLiveData);
paginationNetworkState = Transformations.switchMap(postDataSourceFactory.getPostDataSourceLiveData(),
- dataSource -> dataSource.getPaginationNetworkStateLiveData());
+ (Function<PostDataSource, LiveData<NetworkState>>) PostDataSource::getPaginationNetworkStateLiveData);
PagedList.Config pagedListConfig =
(new PagedList.Config.Builder())
.setEnablePlaceholders(false)
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java
index 1a1c9b37..e467eb0a 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java
@@ -58,8 +58,7 @@ public interface RedditAPI {
Call<String> getInfo(@Path("subredditNamePrefixed") String subredditNamePrefixed, @Query("id") String id);
@GET("subreddits/search.json?raw_json=1&include_over_18=on")
- Call<String> searchSubreddits(@Query("q") String subredditName, @Query("after") String after,
- @HeaderMap Map<String, String> headers);
+ Call<String> searchSubreddits(@Query("q") String subredditName, @Query("after") String after);
@GET("profiles/search.json?raw_json=1")
Call<String> searchProfiles(@Query("q") String profileName, @Query("after") String after,
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java
index a0e08f12..dd72822e 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SearchActivity.java
@@ -70,10 +70,9 @@ public class SearchActivity extends AppCompatActivity {
return mFragment;
}
case 1: {
- PostFragment mFragment = new PostFragment();
+ SubredditListingFragment mFragment = new SubredditListingFragment();
Bundle bundle = new Bundle();
- bundle.putInt(PostFragment.POST_TYPE_KEY, PostDataSource.TYPE_FRONT_PAGE);
- bundle.putString(PostFragment.NAME_KEY, mQuery);
+ bundle.putString(SubredditListingFragment.QUERY_KEY, mQuery);
mFragment.setArguments(bundle);
return mFragment;
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingDataSource.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingDataSource.java
new file mode 100644
index 00000000..80e024d6
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingDataSource.java
@@ -0,0 +1,107 @@
+package ml.docilealligator.infinityforreddit;
+
+import java.util.ArrayList;
+
+import SubredditDatabase.SubredditData;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.MutableLiveData;
+import androidx.paging.PageKeyedDataSource;
+import retrofit2.Retrofit;
+
+public class SubredditListingDataSource extends PageKeyedDataSource<String, SubredditData> {
+ interface OnSubredditListingDataFetchedCallback {
+ void hasSubreddit();
+ void noSubreddit();
+ }
+ private Retrofit retrofit;
+ private String query;
+ private OnSubredditListingDataFetchedCallback onSubredditListingDataFetchedCallback;
+
+ private MutableLiveData<NetworkState> paginationNetworkStateLiveData;
+ private MutableLiveData<NetworkState> initialLoadStateLiveData;
+
+ private LoadInitialParams<String> initialParams;
+ private LoadInitialCallback<String, SubredditData> initialCallback;
+ private LoadParams<String> params;
+ private LoadCallback<String, SubredditData> callback;
+
+ SubredditListingDataSource(Retrofit retrofit, String query,
+ OnSubredditListingDataFetchedCallback onSubredditListingDataFetchedCallback) {
+ this.retrofit = retrofit;
+ this.query = query;
+ this.onSubredditListingDataFetchedCallback = onSubredditListingDataFetchedCallback;
+ paginationNetworkStateLiveData = new MutableLiveData();
+ initialLoadStateLiveData = new MutableLiveData();
+ }
+
+ MutableLiveData getPaginationNetworkStateLiveData() {
+ return paginationNetworkStateLiveData;
+ }
+
+ MutableLiveData getInitialLoadStateLiveData() {
+ return initialLoadStateLiveData;
+ }
+
+ @Override
+ public void loadInitial(@NonNull LoadInitialParams<String> params, @NonNull LoadInitialCallback<String, SubredditData> callback) {
+ initialParams = params;
+ initialCallback = callback;
+
+ initialLoadStateLiveData.postValue(NetworkState.LOADING);
+
+ FetchSubredditData.fetchSubredditListingData(retrofit, query, null, new FetchSubredditData.FetchSubredditListingDataListener() {
+ @Override
+ public void onFetchSubredditListingDataSuccess(ArrayList<SubredditData> subredditData, String after) {
+ if(subredditData.size() == 0) {
+ onSubredditListingDataFetchedCallback.noSubreddit();
+ } else {
+ onSubredditListingDataFetchedCallback.hasSubreddit();
+ }
+
+ callback.onResult(subredditData, null, after);
+ initialLoadStateLiveData.postValue(NetworkState.LOADED);
+ }
+
+ @Override
+ public void onFetchSubredditListingDataFail() {
+ initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error retrieving subreddit list"));
+ }
+ });
+ }
+
+ @Override
+ public void loadBefore(@NonNull LoadParams<String> params, @NonNull LoadCallback<String, SubredditData> callback) {
+
+ }
+
+ @Override
+ public void loadAfter(@NonNull LoadParams<String> params, @NonNull LoadCallback<String, SubredditData> callback) {
+ this.params = params;
+ this.callback = callback;
+
+ if(params.key.equals("null")) {
+ return;
+ }
+
+ FetchSubredditData.fetchSubredditListingData(retrofit, query, params.key, new FetchSubredditData.FetchSubredditListingDataListener() {
+ @Override
+ public void onFetchSubredditListingDataSuccess(ArrayList<SubredditData> subredditData, String after) {
+ callback.onResult(subredditData, after);
+ paginationNetworkStateLiveData.postValue(NetworkState.LOADED);
+ }
+
+ @Override
+ public void onFetchSubredditListingDataFail() {
+ paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error retrieving subreddit list"));
+ }
+ });
+ }
+
+ void retry() {
+ loadInitial(initialParams, initialCallback);
+ }
+
+ void retryLoadingMore() {
+ loadAfter(params, callback);
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingDataSourceFactory.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingDataSourceFactory.java
new file mode 100644
index 00000000..168fadbd
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingDataSourceFactory.java
@@ -0,0 +1,40 @@
+package ml.docilealligator.infinityforreddit;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.MutableLiveData;
+import androidx.paging.DataSource;
+import retrofit2.Retrofit;
+
+public class SubredditListingDataSourceFactory extends DataSource.Factory {
+ private Retrofit retrofit;
+ private String query;
+ private SubredditListingDataSource.OnSubredditListingDataFetchedCallback onSubredditListingDataFetchedCallback;
+
+ private SubredditListingDataSource subredditListingDataSource;
+ private MutableLiveData<SubredditListingDataSource> subredditListingDataSourceMutableLiveData;
+
+ SubredditListingDataSourceFactory(Retrofit retrofit, String query,
+ SubredditListingDataSource.OnSubredditListingDataFetchedCallback onSubredditListingDataFetchedCallback) {
+ this.retrofit = retrofit;
+ this.query = query;
+ this.onSubredditListingDataFetchedCallback = onSubredditListingDataFetchedCallback;
+ subredditListingDataSourceMutableLiveData = new MutableLiveData<>();
+ }
+
+ @NonNull
+ @Override
+ public DataSource create() {
+ SubredditListingDataSource subredditListingDataSource = new SubredditListingDataSource(retrofit,
+ query, onSubredditListingDataFetchedCallback);
+ subredditListingDataSourceMutableLiveData.postValue(subredditListingDataSource);
+ return subredditListingDataSource;
+ }
+
+ public MutableLiveData<SubredditListingDataSource> getSubredditListingDataSourceMutableLiveData() {
+ return subredditListingDataSourceMutableLiveData;
+ }
+
+ SubredditListingDataSource getSubredditListingDataSource() {
+ return subredditListingDataSource;
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingFragment.java
new file mode 100644
index 00000000..f591c4f9
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingFragment.java
@@ -0,0 +1,141 @@
+package ml.docilealligator.infinityforreddit;
+
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.bumptech.glide.Glide;
+import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import SubscribedSubredditDatabase.SubscribedSubredditRoomDatabase;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import retrofit2.Retrofit;
+
+
+/**
+ * A simple {@link Fragment} subclass.
+ */
+public class SubredditListingFragment extends Fragment {
+
+ static final String QUERY_KEY = "QK";
+
+ @BindView(R.id.coordinator_layout_subreddit_listing_fragment) CoordinatorLayout mCoordinatorLayout;
+ @BindView(R.id.recycler_view_subreddit_listing_fragment) RecyclerView mSubredditListingRecyclerView;
+ @BindView(R.id.progress_bar_subreddit_listing_fragment) CircleProgressBar mProgressBar;
+ @BindView(R.id.fetch_subreddit_listing_info_linear_layout_subreddit_listing_fragment) LinearLayout mFetchSubredditListingInfoLinearLayout;
+ @BindView(R.id.fetch_subreddit_listing_info_image_view_subreddit_listing_fragment) ImageView mFetchSubredditListingInfoImageView;
+ @BindView(R.id.fetch_subreddit_listing_info_text_view_subreddit_listing_fragment) TextView mFetchSubredditListingInfoTextView;
+
+ private LinearLayoutManager mLinearLayoutManager;
+
+ private String mQuery;
+
+ private SubredditListingRecyclerViewAdapter mAdapter;
+
+ SubredditListingViewModel mSubredditListingViewModel;
+
+ @Inject @Named("auth_info")
+ SharedPreferences mAuthInfoSharedPreferences;
+
+ @Inject @Named("no_oauth")
+ Retrofit mRetrofit;
+
+ @Inject @Named("oauth")
+ Retrofit mOauthRetrofit;
+
+ public SubredditListingFragment() {
+ // Required empty public constructor
+ }
+
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ // Inflate the layout for this fragment
+ View rootView = inflater.inflate(R.layout.fragment_subreddit_listing, container, false);
+
+ ((Infinity) getActivity().getApplication()).getmNetworkComponent().inject(this);
+
+ ButterKnife.bind(this, rootView);
+
+ mLinearLayoutManager = new LinearLayoutManager(getActivity());
+ mSubredditListingRecyclerView.setLayoutManager(mLinearLayoutManager);
+
+ mQuery = getArguments().getString(QUERY_KEY);
+
+ String accessToken = getActivity().getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE)
+ .getString(SharedPreferencesUtils.ACCESS_TOKEN_KEY, "");
+
+ SubredditListingViewModel.Factory factory = new SubredditListingViewModel.Factory(mRetrofit, mQuery,
+ new SubredditListingDataSource.OnSubredditListingDataFetchedCallback() {
+ @Override
+ public void hasSubreddit() {
+ mFetchSubredditListingInfoLinearLayout.setVisibility(View.GONE);
+ }
+
+ @Override
+ public void noSubreddit() {
+ mFetchSubredditListingInfoLinearLayout.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ //Do nothing
+ }
+ });
+ showErrorView(R.string.no_subreddits);
+ }
+ });
+
+ mAdapter = new SubredditListingRecyclerViewAdapter(getActivity(), mOauthRetrofit, mRetrofit,
+ mAuthInfoSharedPreferences,
+ SubscribedSubredditRoomDatabase.getDatabase(getContext()).subscribedSubredditDao(),
+ () -> mSubredditListingViewModel.retryLoadingMore());
+
+ mSubredditListingRecyclerView.setAdapter(mAdapter);
+
+ mSubredditListingViewModel = ViewModelProviders.of(this, factory).get(SubredditListingViewModel.class);
+ mSubredditListingViewModel.getSubreddits().observe(this, subredditData -> mAdapter.submitList(subredditData));
+
+ mSubredditListingViewModel.getInitialLoadingState().observe(this, networkState -> {
+ if(networkState.getStatus().equals(NetworkState.Status.SUCCESS)) {
+ mProgressBar.setVisibility(View.GONE);
+ } else if(networkState.getStatus().equals(NetworkState.Status.FAILED)) {
+ mFetchSubredditListingInfoLinearLayout.setOnClickListener(view -> mSubredditListingViewModel.retry());
+ showErrorView(R.string.load_posts_error);
+ } else {
+ mFetchSubredditListingInfoLinearLayout.setVisibility(View.GONE);
+ mProgressBar.setVisibility(View.VISIBLE);
+ }
+ });
+
+ mSubredditListingViewModel.getPaginationNetworkState().observe(this, networkState -> {
+ mAdapter.setNetworkState(networkState);
+ });
+
+ return rootView;
+ }
+
+ private void showErrorView(int stringResId) {
+ mProgressBar.setVisibility(View.GONE);
+ if(getActivity() != null && isAdded()) {
+ mFetchSubredditListingInfoLinearLayout.setVisibility(View.VISIBLE);
+ mFetchSubredditListingInfoTextView.setText(stringResId);
+ Glide.with(this).load(R.drawable.load_post_error_indicator).into(mFetchSubredditListingInfoImageView);
+ }
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingRecyclerViewAdapter.java
new file mode 100644
index 00000000..56735c5e
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingRecyclerViewAdapter.java
@@ -0,0 +1,233 @@
+package ml.docilealligator.infinityforreddit;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.RequestManager;
+import com.bumptech.glide.request.RequestOptions;
+
+import SubredditDatabase.SubredditData;
+import SubscribedSubredditDatabase.SubscribedSubredditDao;
+import androidx.annotation.NonNull;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.paging.PagedListAdapter;
+import androidx.recyclerview.widget.DiffUtil;
+import androidx.recyclerview.widget.RecyclerView;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import jp.wasabeef.glide.transformations.RoundedCornersTransformation;
+import pl.droidsonroids.gif.GifImageView;
+import retrofit2.Retrofit;
+
+public class SubredditListingRecyclerViewAdapter extends PagedListAdapter<SubredditData, RecyclerView.ViewHolder> {
+ interface RetryLoadingMoreCallback {
+ void retryLoadingMore();
+ }
+
+ private RequestManager glide;
+
+ private static final int VIEW_TYPE_DATA = 0;
+ private static final int VIEW_TYPE_ERROR = 1;
+ private static final int VIEW_TYPE_LOADING = 2;
+
+ private Context context;
+ private Retrofit oauthRetrofit;
+ private Retrofit retrofit;
+ private SharedPreferences authInfoSharedPreferences;
+ private SubscribedSubredditDao subscribedSubredditDao;
+
+ private NetworkState networkState;
+ private RetryLoadingMoreCallback retryLoadingMoreCallback;
+
+ SubredditListingRecyclerViewAdapter(Context context, Retrofit oauthRetrofit, Retrofit retrofit,
+ SharedPreferences authInfoSharedPreferences,
+ SubscribedSubredditDao subscribedSubredditDao,
+ RetryLoadingMoreCallback retryLoadingMoreCallback) {
+ super(DIFF_CALLBACK);
+ this.context = context;
+ this.oauthRetrofit = oauthRetrofit;
+ this.retrofit = retrofit;
+ this.authInfoSharedPreferences = authInfoSharedPreferences;
+ this.subscribedSubredditDao = subscribedSubredditDao;
+ this.retryLoadingMoreCallback = retryLoadingMoreCallback;
+ glide = Glide.with(context.getApplicationContext());
+ }
+
+ static final DiffUtil.ItemCallback<SubredditData> DIFF_CALLBACK = new DiffUtil.ItemCallback<SubredditData>() {
+ @Override
+ public boolean areItemsTheSame(@NonNull SubredditData oldItem, @NonNull SubredditData newItem) {
+ return oldItem.getId().equals(newItem.getId());
+ }
+
+ @Override
+ public boolean areContentsTheSame(@NonNull SubredditData oldItem, @NonNull SubredditData newItem) {
+ return true;
+ }
+ };
+
+ @NonNull
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ if(viewType == VIEW_TYPE_DATA) {
+ ConstraintLayout constraintLayout = (ConstraintLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_subreddit_listing, parent, false);
+ return new DataViewHolder(constraintLayout);
+ } else if(viewType == VIEW_TYPE_ERROR) {
+ RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_error, parent, false);
+ return new ErrorViewHolder(relativeLayout);
+ } else {
+ RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_loading, parent, false);
+ return new LoadingViewHolder(relativeLayout);
+ }
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
+ if(holder instanceof DataViewHolder) {
+ SubredditData subredditData = getItem(position);
+ ((DataViewHolder) holder).constraintLayout.setOnClickListener(view -> {
+ Intent intent = new Intent(context, ViewSubredditDetailActivity.class);
+ intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, subredditData.getName());
+ context.startActivity(intent);
+ });
+
+ if(subredditData.getIconUrl() != null) {
+ glide.load(subredditData.getIconUrl())
+ .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
+ .error(glide.load(R.drawable.subreddit_default_icon))
+ .into(((DataViewHolder) holder).iconGifImageView);
+ } else {
+ glide.load(R.drawable.subreddit_default_icon)
+ .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
+ .into(((DataViewHolder) holder).iconGifImageView);
+ }
+
+ ((DataViewHolder) holder).subredditNameTextView.setText(subredditData.getName());
+
+ new CheckIsSubscribedToSubredditAsyncTask(subscribedSubredditDao, subredditData.getName(),
+ new CheckIsSubscribedToSubredditAsyncTask.CheckIsSubscribedToSubredditListener() {
+ @Override
+ public void isSubscribed() {
+ ((DataViewHolder) holder).subscribeButton.setVisibility(View.GONE);
+ }
+
+ @Override
+ public void isNotSubscribed() {
+ ((DataViewHolder) holder).subscribeButton.setVisibility(View.VISIBLE);
+ ((DataViewHolder) holder).subscribeButton.setOnClickListener(view -> {
+ SubredditSubscription.subscribeToSubreddit(oauthRetrofit, retrofit,
+ authInfoSharedPreferences, subredditData.getName(), subscribedSubredditDao,
+ new SubredditSubscription.SubredditSubscriptionListener() {
+ @Override
+ public void onSubredditSubscriptionSuccess() {
+ ((DataViewHolder) holder).subscribeButton.setVisibility(View.GONE);
+ Toast.makeText(context, R.string.subscribed, Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void onSubredditSubscriptionFail() {
+ Toast.makeText(context, R.string.subscribe_failed, Toast.LENGTH_SHORT).show();
+ }
+ });
+ });
+ }
+ }).execute();
+ }
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ // Reached at the end
+ if (hasExtraRow() && position == getItemCount() - 1) {
+ if (networkState.getStatus() == NetworkState.Status.LOADING) {
+ return VIEW_TYPE_LOADING;
+ } else {
+ return VIEW_TYPE_ERROR;
+ }
+ } else {
+ return VIEW_TYPE_DATA;
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ if(hasExtraRow()) {
+ return super.getItemCount() + 1;
+ }
+ return super.getItemCount();
+ }
+
+ private boolean hasExtraRow() {
+ return networkState != null && networkState.getStatus() != NetworkState.Status.SUCCESS;
+ }
+
+ void setNetworkState(NetworkState newNetworkState) {
+ NetworkState previousState = this.networkState;
+ boolean previousExtraRow = hasExtraRow();
+ this.networkState = newNetworkState;
+ boolean newExtraRow = hasExtraRow();
+ if (previousExtraRow != newExtraRow) {
+ if (previousExtraRow) {
+ notifyItemRemoved(super.getItemCount());
+ } else {
+ notifyItemInserted(super.getItemCount());
+ }
+ } else if (newExtraRow && !previousState.equals(newNetworkState)) {
+ notifyItemChanged(getItemCount() - 1);
+ }
+ }
+
+ class DataViewHolder extends RecyclerView.ViewHolder {
+ @BindView(R.id.constraint_layout_item_subreddit_listing) ConstraintLayout constraintLayout;
+ @BindView(R.id.subreddit_icon_gif_image_view_item_subreddit_listing) GifImageView iconGifImageView;
+ @BindView(R.id.subreddit_name_text_view_item_subreddit_listing) TextView subredditNameTextView;
+ @BindView(R.id.subscribe_image_view_item_subreddit_listing) ImageView subscribeButton;
+
+ DataViewHolder(View itemView) {
+ super(itemView);
+ ButterKnife.bind(this, itemView);
+ }
+ }
+
+ class ErrorViewHolder extends RecyclerView.ViewHolder {
+ @BindView(R.id.relative_layout_footer_error_item) RelativeLayout relativeLayout;
+ @BindView(R.id.error_text_view_footer_error_item) TextView errorTextView;
+ @BindView(R.id.retry_button_footer_error_item) Button retryButton;
+
+ ErrorViewHolder(View itemView) {
+ super(itemView);
+ ButterKnife.bind(this, itemView);
+ retryButton.setOnClickListener(view -> retryLoadingMoreCallback.retryLoadingMore());
+ errorTextView.setText(R.string.load_comment_failed);
+ }
+ }
+
+ class LoadingViewHolder extends RecyclerView.ViewHolder {
+ @BindView(R.id.progress_bar_footer_progress_bar_item) ProgressBar progressBar;
+
+ LoadingViewHolder(@NonNull View itemView) {
+ super(itemView);
+ ButterKnife.bind(this, itemView);
+ }
+ }
+
+ @Override
+ public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
+ if(holder instanceof DataViewHolder) {
+ glide.clear(((DataViewHolder) holder).iconGifImageView);
+ ((DataViewHolder) holder).subscribeButton.setVisibility(View.GONE);
+ }
+ }
+
+
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingViewModel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingViewModel.java
new file mode 100644
index 00000000..1ebb2dc3
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditListingViewModel.java
@@ -0,0 +1,79 @@
+package ml.docilealligator.infinityforreddit;
+
+import SubredditDatabase.SubredditData;
+import androidx.annotation.NonNull;
+import androidx.arch.core.util.Function;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.Transformations;
+import androidx.lifecycle.ViewModel;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.paging.LivePagedListBuilder;
+import androidx.paging.PagedList;
+import retrofit2.Retrofit;
+
+public class SubredditListingViewModel extends ViewModel {
+ private SubredditListingDataSourceFactory subredditListingDataSourceFactory;
+ private LiveData<NetworkState> paginationNetworkState;
+ private LiveData<NetworkState> initialLoadingState;
+ private LiveData<PagedList<SubredditData>> subreddits;
+
+ SubredditListingViewModel(Retrofit retrofit, String query,
+ SubredditListingDataSource.OnSubredditListingDataFetchedCallback onSubredditListingDataFetchedCallback) {
+ subredditListingDataSourceFactory = new SubredditListingDataSourceFactory(retrofit, query, onSubredditListingDataFetchedCallback);
+
+ initialLoadingState = Transformations.switchMap(subredditListingDataSourceFactory.getSubredditListingDataSourceMutableLiveData(),
+ (Function<SubredditListingDataSource, LiveData<NetworkState>>) SubredditListingDataSource::getInitialLoadStateLiveData);
+ paginationNetworkState = Transformations.switchMap(subredditListingDataSourceFactory.getSubredditListingDataSourceMutableLiveData(),
+ (Function<SubredditListingDataSource, LiveData<NetworkState>>) SubredditListingDataSource::getPaginationNetworkStateLiveData);
+ PagedList.Config pagedListConfig =
+ (new PagedList.Config.Builder())
+ .setEnablePlaceholders(false)
+ .setPageSize(25)
+ .build();
+
+ subreddits = (new LivePagedListBuilder(subredditListingDataSourceFactory, pagedListConfig)).build();
+ }
+
+ LiveData<PagedList<SubredditData>> getSubreddits() {
+ return subreddits;
+ }
+
+ LiveData<NetworkState> getPaginationNetworkState() {
+ return paginationNetworkState;
+ }
+
+ LiveData<NetworkState> getInitialLoadingState() {
+ return initialLoadingState;
+ }
+
+ void refresh() {
+ subredditListingDataSourceFactory.getSubredditListingDataSource().invalidate();
+ }
+
+ void retry() {
+ subredditListingDataSourceFactory.getSubredditListingDataSource().retry();
+ }
+
+ void retryLoadingMore() {
+ subredditListingDataSourceFactory.getSubredditListingDataSource().retryLoadingMore();
+ }
+
+ public static class Factory extends ViewModelProvider.NewInstanceFactory {
+ private Retrofit retrofit;
+ private String query;
+ private SubredditListingDataSource.OnSubredditListingDataFetchedCallback onSubredditListingDataFetchedCallback;
+
+ public Factory(Retrofit retrofit, String query,
+ SubredditListingDataSource.OnSubredditListingDataFetchedCallback onSubredditListingDataFetchedCallback) {
+ this.retrofit = retrofit;
+ this.query = query;
+ this.onSubredditListingDataFetchedCallback = onSubredditListingDataFetchedCallback;
+ }
+
+ @NonNull
+ @Override
+ public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
+ return (T) new SubredditListingViewModel(retrofit, query, onSubredditListingDataFetchedCallback);
+ }
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditSubscription.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditSubscription.java
index ceb73e3b..9ede0db5 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditSubscription.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SubredditSubscription.java
@@ -2,7 +2,6 @@ package ml.docilealligator.infinityforreddit;
import android.content.SharedPreferences;
import android.os.AsyncTask;
-import androidx.annotation.NonNull;
import android.util.Log;
import java.util.HashMap;
@@ -11,6 +10,7 @@ import java.util.Map;
import SubredditDatabase.SubredditData;
import SubscribedSubredditDatabase.SubscribedSubredditDao;
import SubscribedSubredditDatabase.SubscribedSubredditData;
+import androidx.annotation.NonNull;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
@@ -55,8 +55,10 @@ class SubredditSubscription {
if(action.equals("sub")) {
FetchSubredditData.fetchSubredditData(retrofit, subredditName, new FetchSubredditData.FetchSubredditDataListener() {
@Override
- public void onFetchSubredditDataSuccess(String response) {
- ParseSubredditData.parseSubredditData(response, new ParseSubredditData.ParseSubredditDataListener() {
+ public void onFetchSubredditDataSuccess(SubredditData subredditData, int nCurrentOnlineSubscribers) {
+ new UpdateSubscriptionAsyncTask(subscribedSubredditDao,
+ subredditData, true).execute();
+ /*ParseSubredditData.parseSubredditData(response, new ParseSubredditData.ParseSubredditDataListener() {
@Override
public void onParseSubredditDataSuccess(SubredditData subredditData, int nCurrentOnlineSubscribers) {
new UpdateSubscriptionAsyncTask(subscribedSubredditDao,
@@ -67,7 +69,7 @@ class SubredditSubscription {
public void onParseSubredditDataFail() {
}
- });
+ });*/
}
@Override
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java
index 831a22ff..b4127233 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java
@@ -1,18 +1,9 @@
package ml.docilealligator.infinityforreddit;
-import androidx.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
-import com.google.android.material.chip.Chip;
-import com.google.android.material.appbar.AppBarLayout;
-import com.google.android.material.appbar.CollapsingToolbarLayout;
-import androidx.coordinatorlayout.widget.CoordinatorLayout;
-import com.google.android.material.snackbar.Snackbar;
-import androidx.fragment.app.Fragment;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -23,6 +14,10 @@ import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import com.bumptech.glide.request.RequestOptions;
+import com.google.android.material.appbar.AppBarLayout;
+import com.google.android.material.appbar.CollapsingToolbarLayout;
+import com.google.android.material.chip.Chip;
+import com.google.android.material.snackbar.Snackbar;
import javax.inject.Inject;
import javax.inject.Named;
@@ -32,8 +27,12 @@ import SubredditDatabase.SubredditData;
import SubredditDatabase.SubredditRoomDatabase;
import SubredditDatabase.SubredditViewModel;
import SubscribedSubredditDatabase.SubscribedSubredditDao;
-import SubscribedSubredditDatabase.SubscribedSubredditData;
import SubscribedSubredditDatabase.SubscribedSubredditRoomDatabase;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProviders;
import butterknife.BindView;
import butterknife.ButterKnife;
import jp.wasabeef.glide.transformations.RoundedCornersTransformation;
@@ -244,8 +243,12 @@ public class ViewSubredditDetailActivity extends AppCompatActivity {
FetchSubredditData.fetchSubredditData(mRetrofit, subredditName, new FetchSubredditData.FetchSubredditDataListener() {
@Override
- public void onFetchSubredditDataSuccess(String response) {
- ParseSubredditData.parseSubredditData(response, new ParseSubredditData.ParseSubredditDataListener() {
+ public void onFetchSubredditDataSuccess(SubredditData subredditData, int nCurrentOnlineSubscribers) {
+ new InsertSubredditDataAsyncTask(SubredditRoomDatabase.getDatabase(ViewSubredditDetailActivity.this), subredditData)
+ .execute();
+ String nOnlineSubscribers = getString(R.string.online_subscribers_number_detail, nCurrentOnlineSubscribers);
+ nOnlineSubscribersTextView.setText(nOnlineSubscribers);
+ /*ParseSubredditData.parseSubredditData(response, new ParseSubredditData.ParseSubredditDataListener() {
@Override
public void onParseSubredditDataSuccess(SubredditData subredditData, int nCurrentOnlineSubscribers) {
new InsertSubredditDataAsyncTask(SubredditRoomDatabase.getDatabase(ViewSubredditDetailActivity.this), subredditData)
@@ -258,7 +261,7 @@ public class ViewSubredditDetailActivity extends AppCompatActivity {
public void onParseSubredditDataFail() {
makeSnackbar(R.string.cannot_fetch_subreddit_info);
}
- });
+ });*/
}
@Override
@@ -329,7 +332,7 @@ public class ViewSubredditDetailActivity extends AppCompatActivity {
}
}
- private static class CheckIsSubscribedToSubredditAsyncTask extends AsyncTask<Void, Void, Void> {
+ /*private static class CheckIsSubscribedToSubredditAsyncTask extends AsyncTask<Void, Void, Void> {
private SubscribedSubredditDao subscribedSubredditDao;
private String subredditName;
@@ -363,5 +366,5 @@ public class ViewSubredditDetailActivity extends AppCompatActivity {
checkIsSubscribedToSubredditListener.isNotSubscribed();
}
}
- }
+ }*/
}
diff --git a/app/src/main/res/layout/fragment_subreddit_listing.xml b/app/src/main/res/layout/fragment_subreddit_listing.xml
new file mode 100644
index 00000000..d6fba93a
--- /dev/null
+++ b/app/src/main/res/layout/fragment_subreddit_listing.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/coordinator_layout_subreddit_listing_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ tools:context=".SubredditListingFragment">
+
+ <com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar
+ android:id="@+id/progress_bar_subreddit_listing_fragment"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:layout_marginBottom="16dp"
+ app:mlpb_progress_stoke_width="3dp"
+ app:mlpb_progress_color="@color/colorAccent"
+ android:layout_gravity="center_horizontal"/>
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/recycler_view_subreddit_listing_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <LinearLayout
+ android:id="@+id/fetch_subreddit_listing_info_linear_layout_subreddit_listing_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:orientation="vertical"
+ android:visibility="gone">
+
+ <ImageView
+ android:id="@+id/fetch_subreddit_listing_info_image_view_subreddit_listing_fragment"
+ android:layout_width="150dp"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:id="@+id/fetch_subreddit_listing_info_text_view_subreddit_listing_fragment"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:gravity="center" />
+
+ </LinearLayout>
+
+</androidx.coordinatorlayout.widget.CoordinatorLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/item_footer_error.xml b/app/src/main/res/layout/item_footer_error.xml
index bd653604..e1d3c14b 100644
--- a/app/src/main/res/layout/item_footer_error.xml
+++ b/app/src/main/res/layout/item_footer_error.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/relative_layout_footer_progress_bar_item"
+ android:id="@+id/relative_layout_footer_error_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
@@ -9,16 +9,16 @@
android:layout_marginBottom="16dp">
<TextView
+ android:id="@+id/error_text_view_footer_error_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
- android:layout_toStartOf="@id/retry_button_footer_progress_bar_item"
- android:text="@string/load_data_failed"
+ android:layout_toStartOf="@id/retry_button_footer_error_item"
android:textSize="18sp" />
<Button
- android:id="@+id/retry_button_footer_progress_bar_item"
+ android:id="@+id/retry_button_footer_error_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
diff --git a/app/src/main/res/layout/item_subreddit_listing.xml b/app/src/main/res/layout/item_subreddit_listing.xml
new file mode 100644
index 00000000..10d5055a
--- /dev/null
+++ b/app/src/main/res/layout/item_subreddit_listing.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/constraint_layout_item_subreddit_listing"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="16dp"
+ android:clickable="true"
+ android:focusable="true"
+ android:background="?attr/selectableItemBackground">
+
+ <pl.droidsonroids.gif.GifImageView
+ android:id="@+id/subreddit_icon_gif_image_view_item_subreddit_listing"
+ android:layout_width="36dp"
+ android:layout_height="36dp"
+ android:layout_gravity="center_vertical"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"/>
+
+ <TextView
+ android:id="@+id/subreddit_name_text_view_item_subreddit_listing"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="32dp"
+ android:textColor="@android:color/black"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@+id/subreddit_icon_gif_image_view_item_subreddit_listing"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <ImageView
+ android:id="@+id/subscribe_image_view_item_subreddit_listing"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+
+ android:src="@drawable/baseline_add_white_24"
+ android:tint="@color/colorPrimary"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ android:clickable="true"
+ android:focusable="true"
+ android:background="?attr/selectableItemBackground"
+ android:visibility="gone"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a8058872..d286b264 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -14,8 +14,9 @@
<string name="tap_to_retry">Error loading image. Tap to retry.</string>
<string name="load_posts_error">Error loading posts.\nTap to retry.</string>
<string name="no_posts">No posts here.</string>
+ <string name="no_subreddits">No subreddits found.</string>
- <string name="load_data_failed">Cannot load posts</string>
+ <string name="load_posts_failed">Error loading posts</string>
<string name="load_comment_failed">Error loading comments</string>
<string name="load_more_comment_failed">Error loading more comments</string>
<string name="retry">Retry</string>
@@ -56,9 +57,5 @@
<string name="app_label">Infinity</string>
<string name="search_hint">Search anything</string>
- <string name="title_activity_search">Search</string>
- <string name="section_format">Hello World from section: %1$d</string>
- <string name="tab_text_1">Tab 1</string>
- <string name="tab_text_2">Tab 2</string>
- <string name="tab_text_3">Tab 3</string>
+
</resources>