aboutsummaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
authorAlex Ning <chineseperson5@gmail.com>2020-09-17 03:08:06 +0000
committerAlex Ning <chineseperson5@gmail.com>2020-09-17 03:08:06 +0000
commita3367c193b2b9f6e385c155e543debd9f2bb3426 (patch)
tree7d2f3307682a697225763aa6977ad050283c151e /app/src
parent9979c91b3cc58a13e72e84208d1b79f71ee0dc50 (diff)
downloadinfinity-for-reddit-a3367c193b2b9f6e385c155e543debd9f2bb3426.tar
infinity-for-reddit-a3367c193b2b9f6e385c155e543debd9f2bb3426.tar.gz
infinity-for-reddit-a3367c193b2b9f6e385c155e543debd9f2bb3426.tar.bz2
infinity-for-reddit-a3367c193b2b9f6e385c155e543debd9f2bb3426.tar.lz
infinity-for-reddit-a3367c193b2b9f6e385c155e543debd9f2bb3426.tar.xz
infinity-for-reddit-a3367c193b2b9f6e385c155e543debd9f2bb3426.tar.zst
infinity-for-reddit-a3367c193b2b9f6e385c155e543debd9f2bb3426.zip
Select user flair in subreddits.
Diffstat (limited to 'app/src')
-rw-r--r--app/src/main/AndroidManifest.xml6
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/API/RedditAPI.java8
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SelectUserFlairActivity.java261
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java9
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/UserFlairRecyclerViewAdapter.java88
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java3
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/FetchUserFlairs.java122
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/SelectUserFlair.java105
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/UserFlair.java78
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/Utils/JSONUtils.java2
-rw-r--r--app/src/main/res/drawable/ic_outline_edit_24px.xml9
-rw-r--r--app/src/main/res/layout/activity_select_user_flair.xml32
-rw-r--r--app/src/main/res/layout/item_flair.xml3
-rw-r--r--app/src/main/res/layout/item_user_flair.xml32
-rw-r--r--app/src/main/res/menu/view_subreddit_detail_activity.xml6
-rw-r--r--app/src/main/res/values/strings.xml5
16 files changed, 758 insertions, 11 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9d545e5b..4bcabf59 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,11 @@
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
tools:replace="android:label">
- <activity android:name=".Activity.CommentFullMarkdownActivity"
+ <activity android:name=".Activity.SelectUserFlairActivity"
+ android:parentActivityName=".Activity.MainActivity"
+ android:theme="@style/AppTheme.Slidable" />
+ <activity
+ android:name=".Activity.CommentFullMarkdownActivity"
android:parentActivityName=".Activity.MainActivity"
android:theme="@style/AppTheme.Slidable" />
<activity
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/API/RedditAPI.java b/app/src/main/java/ml/docilealligator/infinityforreddit/API/RedditAPI.java
index 003ad955..c4589206 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/API/RedditAPI.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/API/RedditAPI.java
@@ -318,4 +318,12 @@ public interface RedditAPI {
@FormUrlEncoded
@POST("api/block_user")
Call<String> blockUser(@HeaderMap Map<String, String> headers, @FieldMap Map<String, String> params);
+
+ @GET("r/{subredditName}/api/user_flair_v2.json?raw_json=1")
+ Call<String> getUserFlairs(@HeaderMap Map<String, String> headers, @Path("subredditName") String subredditName);
+
+ @FormUrlEncoded
+ @POST("/r/{subredditName}/api/selectflair?raw_json=1")
+ Call<String> selectUserFlair(@HeaderMap Map<String, String> headers, @FieldMap Map<String, String> params,
+ @Path("subredditName") String subredditName);
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SelectUserFlairActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SelectUserFlairActivity.java
new file mode 100644
index 00000000..e90432f3
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/SelectUserFlairActivity.java
@@ -0,0 +1,261 @@
+package ml.docilealligator.infinityforreddit.Activity;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.widget.Toolbar;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.google.android.material.appbar.AppBarLayout;
+import com.google.android.material.dialog.MaterialAlertDialogBuilder;
+import com.google.android.material.snackbar.Snackbar;
+import com.r0adkll.slidr.Slidr;
+
+import java.util.ArrayList;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import ml.docilealligator.infinityforreddit.ActivityToolbarInterface;
+import ml.docilealligator.infinityforreddit.Adapter.UserFlairRecyclerViewAdapter;
+import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask;
+import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.FetchUserFlairs;
+import ml.docilealligator.infinityforreddit.Infinity;
+import ml.docilealligator.infinityforreddit.R;
+import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase;
+import ml.docilealligator.infinityforreddit.SelectUserFlair;
+import ml.docilealligator.infinityforreddit.UserFlair;
+import ml.docilealligator.infinityforreddit.Utils.SharedPreferencesUtils;
+import retrofit2.Retrofit;
+
+public class SelectUserFlairActivity extends BaseActivity implements ActivityToolbarInterface {
+
+ public static final String EXTRA_SUBREDDIT_NAME = "ESN";
+ private static final String NULL_ACCESS_TOKEN_STATE = "NATS";
+ private static final String ACCESS_TOKEN_STATE = "ATS";
+ private static final String ACCOUNT_NAME_STATE = "ANS";
+ private static final String USER_FLAIRS_STATE = "UFS";
+
+ @BindView(R.id.coordinator_layout_select_user_flair_activity)
+ CoordinatorLayout coordinatorLayout;
+ @BindView(R.id.appbar_layout_select_user_flair_activity)
+ AppBarLayout appBarLayout;
+ @BindView(R.id.toolbar_select_user_flair_activity)
+ Toolbar toolbar;
+ @BindView(R.id.recycler_view_select_user_flair_activity)
+ RecyclerView recyclerView;
+ @Inject
+ @Named("oauth")
+ Retrofit mOauthRetrofit;
+ @Inject
+ RedditDataRoomDatabase mRedditDataRoomDatabase;
+ @Inject
+ @Named("default")
+ SharedPreferences mSharedPreferences;
+ @Inject
+ CustomThemeWrapper mCustomThemeWrapper;
+ private LinearLayoutManager mLinearLayoutManager;
+ private boolean mNullAccessToken = false;
+ private String mAccessToken;
+ private String mAccountName;
+ private ArrayList<UserFlair> mUserFlairs;
+ private String mSubredditName;
+ private UserFlairRecyclerViewAdapter mAdapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ ((Infinity) getApplication()).getAppComponent().inject(this);
+
+ setImmersiveModeNotApplicable();
+
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_select_user_flair);
+
+ ButterKnife.bind(this);
+
+ applyCustomTheme();
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && isChangeStatusBarIconColor()) {
+ addOnOffsetChangedListener(appBarLayout);
+ }
+
+ if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) {
+ Slidr.attach(this);
+ }
+
+ setSupportActionBar(toolbar);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ setToolbarGoToTop(toolbar);
+
+ mSubredditName = getIntent().getStringExtra(EXTRA_SUBREDDIT_NAME);
+ setTitle(mSubredditName);
+
+ if (savedInstanceState != null) {
+ mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE);
+ mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE);
+ mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE);
+ mUserFlairs = savedInstanceState.getParcelableArrayList(USER_FLAIRS_STATE);
+
+ if (!mNullAccessToken && mAccessToken == null) {
+ getCurrentAccountAndBindView();
+ } else {
+ bindView();
+ }
+ } else {
+ getCurrentAccountAndBindView();
+ }
+ }
+
+ private void getCurrentAccountAndBindView() {
+ new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> {
+ if (account == null) {
+ mNullAccessToken = true;
+ } else {
+ mAccessToken = account.getAccessToken();
+ mAccountName = account.getUsername();
+ }
+ bindView();
+ }).execute();
+ }
+
+ private void bindView() {
+ if (mUserFlairs == null) {
+ FetchUserFlairs.fetchUserFlairsInSubreddit(mOauthRetrofit, mAccessToken, mSubredditName,
+ new FetchUserFlairs.FetchUserFlairsInSubredditListener() {
+ @Override
+ public void fetchSuccessful(ArrayList<UserFlair> userFlairs) {
+ mUserFlairs = userFlairs;
+ instantiateRecyclerView();
+ }
+
+ @Override
+ public void fetchFailed() {
+
+ }
+ });
+ } else {
+ instantiateRecyclerView();
+ }
+ }
+
+ private void instantiateRecyclerView() {
+ mAdapter = new UserFlairRecyclerViewAdapter(mCustomThemeWrapper, mUserFlairs, (userFlair, editUserFlair) -> {
+ if (editUserFlair) {
+ View dialogView = getLayoutInflater().inflate(R.layout.dialog_edit_flair, null);
+ EditText flairEditText = dialogView.findViewById(R.id.flair_edit_text_edit_flair_dialog);
+ flairEditText.setText(userFlair.getText());
+ flairEditText.requestFocus();
+ InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ if (imm != null) {
+ imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
+ }
+ new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme)
+ .setTitle(R.string.edit_flair)
+ .setView(dialogView)
+ .setPositiveButton(R.string.ok, (dialogInterface, i)
+ -> {
+ if (imm != null) {
+ imm.hideSoftInputFromWindow(flairEditText.getWindowToken(), 0);
+ }
+ userFlair.setText(flairEditText.getText().toString());
+ selectUserFlair(userFlair);
+ })
+ .setNegativeButton(R.string.cancel, (dialogInterface, i) -> {
+ if (imm != null) {
+ imm.hideSoftInputFromWindow(flairEditText.getWindowToken(), 0);
+ }
+ })
+ .setOnDismissListener(dialogInterface -> {
+ if (imm != null) {
+ imm.hideSoftInputFromWindow(flairEditText.getWindowToken(), 0);
+ }
+ })
+ .show();
+ } else {
+ new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme)
+ .setTitle(R.string.select_this_user_flair)
+ .setMessage(userFlair.getText())
+ .setPositiveButton(R.string.yes, (dialogInterface, i) -> selectUserFlair(userFlair))
+ .setNegativeButton(R.string.no, null)
+ .show();
+ }
+ });
+ mLinearLayoutManager = new LinearLayoutManager(SelectUserFlairActivity.this);
+ recyclerView.setLayoutManager(mLinearLayoutManager);
+ recyclerView.setAdapter(mAdapter);
+ }
+
+ private void selectUserFlair(UserFlair userFlair) {
+ SelectUserFlair.selectUserFlair(mOauthRetrofit, mAccessToken, userFlair, mSubredditName, mAccountName,
+ new SelectUserFlair.SelectUserFlairListener() {
+ @Override
+ public void success() {
+ Toast.makeText(SelectUserFlairActivity.this, R.string.select_user_flair_success, Toast.LENGTH_SHORT).show();
+ finish();
+ }
+
+ @Override
+ public void failed(String errorMessage) {
+ if (errorMessage == null || errorMessage.equals("")) {
+ Snackbar.make(coordinatorLayout, R.string.select_user_flair_success, Snackbar.LENGTH_SHORT).show();
+ } else {
+ Snackbar.make(coordinatorLayout, errorMessage, Snackbar.LENGTH_SHORT).show();
+ }
+ }
+ });
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected void onSaveInstanceState(@NonNull Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken);
+ outState.putString(ACCESS_TOKEN_STATE, mAccessToken);
+ outState.putString(ACCOUNT_NAME_STATE, mAccountName);
+ outState.putParcelableArrayList(USER_FLAIRS_STATE, mUserFlairs);
+ }
+
+ @Override
+ protected SharedPreferences getDefaultSharedPreferences() {
+ return mSharedPreferences;
+ }
+
+ @Override
+ protected CustomThemeWrapper getCustomThemeWrapper() {
+ return mCustomThemeWrapper;
+ }
+
+ @Override
+ protected void applyCustomTheme() {
+ coordinatorLayout.setBackgroundColor(mCustomThemeWrapper.getBackgroundColor());
+ applyAppBarLayoutAndToolbarTheme(appBarLayout, toolbar);
+ }
+
+ @Override
+ public void onLongPress() {
+ if (mLinearLayoutManager != null) {
+ mLinearLayoutManager.scrollToPositionWithOffset(0, 0);
+ }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java
index 8b688f63..5982ee7e 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewSubredditDetailActivity.java
@@ -749,6 +749,15 @@ public class ViewSubredditDetailActivity extends BaseActivity implements SortTyp
case R.id.action_change_post_layout_view_subreddit_detail_activity:
postLayoutBottomSheetFragment.show(getSupportFragmentManager(), postLayoutBottomSheetFragment.getTag());
return true;
+ case R.id.action_select_user_flair_view_subreddit_detail_activity:
+ if (mAccessToken == null) {
+ Toast.makeText(this, R.string.login_first, Toast.LENGTH_SHORT).show();
+ return true;
+ }
+ Intent selectUserFlairIntent = new Intent(this, SelectUserFlairActivity.class);
+ selectUserFlairIntent.putExtra(SelectUserFlairActivity.EXTRA_SUBREDDIT_NAME, subredditName);
+ startActivity(selectUserFlairIntent);
+ return true;
case R.id.action_share_view_subreddit_detail_activity:
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/UserFlairRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/UserFlairRecyclerViewAdapter.java
new file mode 100644
index 00000000..e0669959
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/UserFlairRecyclerViewAdapter.java
@@ -0,0 +1,88 @@
+package ml.docilealligator.infinityforreddit.Adapter;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.ArrayList;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.R;
+import ml.docilealligator.infinityforreddit.UserFlair;
+import ml.docilealligator.infinityforreddit.Utils.Utils;
+
+public class UserFlairRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+ private CustomThemeWrapper customThemeWrapper;
+ private ArrayList<UserFlair> userFlairs;
+ private ItemClickListener itemClickListener;
+
+ public UserFlairRecyclerViewAdapter(CustomThemeWrapper customThemeWrapper, ArrayList<UserFlair> userFlairs,
+ ItemClickListener itemClickListener) {
+ this.customThemeWrapper = customThemeWrapper;
+ this.userFlairs = userFlairs;
+ this.itemClickListener = itemClickListener;
+ }
+
+ public interface ItemClickListener {
+ void onClick(UserFlair userFlair, boolean editUserFlair);
+ }
+
+ @NonNull
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ return new UserFlairViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_user_flair, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
+ if (holder instanceof UserFlairViewHolder) {
+ UserFlair userFlair = userFlairs.get(holder.getAdapterPosition());
+ if (userFlair.getHtmlText() == null || userFlair.getHtmlText().equals("")) {
+ ((UserFlairViewHolder) holder).userFlairHtmlTextView.setText(userFlair.getText());
+ } else {
+ Utils.setHTMLWithImageToTextView(((UserFlairViewHolder) holder).userFlairHtmlTextView, userFlair.getHtmlText());
+ }
+ if (userFlair.isEditable()) {
+ ((UserFlairViewHolder) holder).editUserFlairImageView.setVisibility(View.VISIBLE);
+ } else {
+ ((UserFlairViewHolder) holder).editUserFlairImageView.setVisibility(View.GONE);
+ }
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return userFlairs == null ? 0 : userFlairs.size();
+ }
+
+ class UserFlairViewHolder extends RecyclerView.ViewHolder {
+
+ @BindView(R.id.user_flair_html_text_view_item_user_flair)
+ TextView userFlairHtmlTextView;
+ @BindView(R.id.edit_user_flair_image_view_item_user_flair)
+ ImageView editUserFlairImageView;
+
+ public UserFlairViewHolder(@NonNull View itemView) {
+ super(itemView);
+ ButterKnife.bind(this, itemView);
+
+ userFlairHtmlTextView.setTextColor(customThemeWrapper.getPrimaryTextColor());
+ editUserFlairImageView.setColorFilter(customThemeWrapper.getPrimaryTextColor(), android.graphics.PorterDuff.Mode.SRC_IN);
+
+ itemView.setOnClickListener(view -> {
+ itemClickListener.onClick(userFlairs.get(getAdapterPosition()), false);
+ });
+
+ editUserFlairImageView.setOnClickListener(view -> {
+ itemClickListener.onClick(userFlairs.get(getAdapterPosition()), true);
+ });
+ }
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java
index 9b40041d..328b3714 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java
@@ -27,6 +27,7 @@ import ml.docilealligator.infinityforreddit.Activity.RulesActivity;
import ml.docilealligator.infinityforreddit.Activity.SearchActivity;
import ml.docilealligator.infinityforreddit.Activity.SearchResultActivity;
import ml.docilealligator.infinityforreddit.Activity.SearchSubredditsResultActivity;
+import ml.docilealligator.infinityforreddit.Activity.SelectUserFlairActivity;
import ml.docilealligator.infinityforreddit.Activity.SelectedSubredditsActivity;
import ml.docilealligator.infinityforreddit.Activity.SendPrivateMessageActivity;
import ml.docilealligator.infinityforreddit.Activity.SettingsActivity;
@@ -200,4 +201,6 @@ public interface AppComponent {
void inject(SubmitCrosspostActivity submitCrosspostActivity);
void inject(CommentFullMarkdownActivity commentFullMarkdownActivity);
+
+ void inject(SelectUserFlairActivity selectUserFlairActivity);
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/FetchUserFlairs.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchUserFlairs.java
new file mode 100644
index 00000000..5d3586bc
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchUserFlairs.java
@@ -0,0 +1,122 @@
+package ml.docilealligator.infinityforreddit;
+
+import android.os.AsyncTask;
+import android.text.Html;
+
+import androidx.annotation.NonNull;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+
+import ml.docilealligator.infinityforreddit.API.RedditAPI;
+import ml.docilealligator.infinityforreddit.Utils.APIUtils;
+import ml.docilealligator.infinityforreddit.Utils.JSONUtils;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+
+public class FetchUserFlairs {
+ public static void fetchUserFlairsInSubreddit(Retrofit oauthRetrofit, String accessToken, String subredditName, FetchUserFlairsInSubredditListener fetchUserFlairsInSubredditListener) {
+ RedditAPI api = oauthRetrofit.create(RedditAPI.class);
+
+ Call<String> flairsCall = api.getUserFlairs(APIUtils.getOAuthHeader(accessToken), subredditName);
+ flairsCall.enqueue(new Callback<String>() {
+ @Override
+ public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
+ if (response.isSuccessful()) {
+ new ParseUserFlairsAsyncTask(response.body(), new ParseUserFlairsAsyncTask.ParseUserFlairsAsyncTaskListener() {
+ @Override
+ public void parseSuccessful(ArrayList<UserFlair> userFlairs) {
+ fetchUserFlairsInSubredditListener.fetchSuccessful(userFlairs);
+ }
+
+ @Override
+ public void parseFailed() {
+ fetchUserFlairsInSubredditListener.fetchFailed();
+ }
+ }).execute();
+ } else if (response.code() == 403) {
+ //No flairs
+ fetchUserFlairsInSubredditListener.fetchSuccessful(null);
+ } else {
+ fetchUserFlairsInSubredditListener.fetchFailed();
+ }
+ }
+
+ @Override
+ public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
+ fetchUserFlairsInSubredditListener.fetchFailed();
+ }
+ });
+ }
+
+ public interface FetchUserFlairsInSubredditListener {
+ void fetchSuccessful(ArrayList<UserFlair> userFlairs);
+
+ void fetchFailed();
+ }
+
+ private static class ParseUserFlairsAsyncTask extends AsyncTask<Void, ArrayList<UserFlair>, ArrayList<UserFlair>> {
+ private String response;
+ private ParseUserFlairsAsyncTaskListener parseFlairsAsyncTaskListener;
+
+ ParseUserFlairsAsyncTask(String response, ParseUserFlairsAsyncTaskListener parseFlairsAsyncTaskListener) {
+ this.response = response;
+ this.parseFlairsAsyncTaskListener = parseFlairsAsyncTaskListener;
+ }
+
+ @Override
+ protected ArrayList<UserFlair> doInBackground(Void... voids) {
+ try {
+ JSONArray jsonArray = new JSONArray(response);
+ ArrayList<UserFlair> userFlairs = new ArrayList<>();
+ for (int i = 0; i < jsonArray.length(); i++) {
+ JSONObject userFlairObject = jsonArray.getJSONObject(i);
+ String id = userFlairObject.getString(JSONUtils.ID_KEY);
+ String text = userFlairObject.getString(JSONUtils.TEXT_KEY);
+ boolean editable = userFlairObject.getBoolean(JSONUtils.TEXT_EDITABLE_KEY);
+ int maxEmojis = userFlairObject.getInt(JSONUtils.MAX_EMOJIS_KEY);
+
+ StringBuilder authorFlairHTMLBuilder = new StringBuilder();
+ if (userFlairObject.has(JSONUtils.RICHTEXT_KEY)) {
+ JSONArray flairArray = userFlairObject.getJSONArray(JSONUtils.RICHTEXT_KEY);
+ for (int j = 0; j < flairArray.length(); j++) {
+ JSONObject flairObject = flairArray.getJSONObject(j);
+ String e = flairObject.getString(JSONUtils.E_KEY);
+ if (e.equals("text")) {
+ authorFlairHTMLBuilder.append(Html.escapeHtml(flairObject.getString(JSONUtils.T_KEY)));
+ } else if (e.equals("emoji")) {
+ authorFlairHTMLBuilder.append("<img src=\"").append(Html.escapeHtml(flairObject.getString(JSONUtils.U_KEY))).append("\">");
+ }
+ }
+ }
+
+ userFlairs.add(new UserFlair(id, text, authorFlairHTMLBuilder.toString(), editable, maxEmojis));
+ }
+ return userFlairs;
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(ArrayList<UserFlair> userFlairs) {
+ if (userFlairs != null) {
+ parseFlairsAsyncTaskListener.parseSuccessful(userFlairs);
+ } else {
+ parseFlairsAsyncTaskListener.parseFailed();
+ }
+ }
+
+ interface ParseUserFlairsAsyncTaskListener {
+ void parseSuccessful(ArrayList<UserFlair> userFlairs);
+
+ void parseFailed();
+ }
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SelectUserFlair.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SelectUserFlair.java
new file mode 100644
index 00000000..92761426
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SelectUserFlair.java
@@ -0,0 +1,105 @@
+package ml.docilealligator.infinityforreddit;
+
+import android.os.AsyncTask;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import ml.docilealligator.infinityforreddit.API.RedditAPI;
+import ml.docilealligator.infinityforreddit.Utils.APIUtils;
+import ml.docilealligator.infinityforreddit.Utils.JSONUtils;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+
+public class SelectUserFlair {
+ public interface SelectUserFlairListener {
+ void success();
+ void failed(String errorMessage);
+ }
+
+ public static void selectUserFlair(Retrofit oauthRetrofit, String accessToken, UserFlair userFlair,
+ String subredditName, String accountName, SelectUserFlairListener selectUserFlairListener) {
+ Map<String, String> params = new HashMap<>();
+ params.put(APIUtils.API_TYPE_KEY, APIUtils.API_TYPE_JSON);
+ params.put(APIUtils.FLAIR_TEMPLATE_ID_KEY, userFlair.getId());
+ params.put(APIUtils.NAME_KEY, accountName);
+ params.put(APIUtils.TEXT_KEY, userFlair.getText());
+ oauthRetrofit.create(RedditAPI.class).selectUserFlair(APIUtils.getOAuthHeader(accessToken), params, subredditName)
+ .enqueue(new Callback<String>() {
+ @Override
+ public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
+ if (response.isSuccessful()) {
+ new ParseErrorAsyncTask(response.body(), selectUserFlairListener).execute();
+ } else {
+ selectUserFlairListener.failed(response.message());
+ }
+ }
+
+ @Override
+ public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
+ selectUserFlairListener.failed(t.getMessage());
+ }
+ });
+ }
+
+ private static class ParseErrorAsyncTask extends AsyncTask<Void, Void, Void> {
+
+ private String response;
+ @Nullable
+ private String errorMessage;
+ private SelectUserFlairListener selectUserFlairListener;
+
+ interface ParseErrorAsyncTaskListener {
+ void parseFinished(@Nullable String errorMessage);
+ }
+
+ ParseErrorAsyncTask(String response, SelectUserFlairListener selectUserFlairListener) {
+ this.response = response;
+ this.selectUserFlairListener = selectUserFlairListener;
+ }
+
+ @Override
+ protected Void doInBackground(Void... voids) {
+ try {
+ JSONObject responseObject = new JSONObject(response).getJSONObject(JSONUtils.JSON_KEY);
+
+ if (responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() != 0) {
+ JSONArray error = responseObject.getJSONArray(JSONUtils.ERRORS_KEY)
+ .getJSONArray(responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() - 1);
+ if (error.length() != 0) {
+ String errorString;
+ if (error.length() >= 2) {
+ errorString = error.getString(1);
+ } else {
+ errorString = error.getString(0);
+ }
+ errorMessage = errorString.substring(0, 1).toUpperCase() + errorString.substring(1);
+ }
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ super.onPostExecute(aVoid);
+ if (errorMessage == null) {
+ selectUserFlairListener.success();
+ } else {
+ selectUserFlairListener.failed(errorMessage);
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/UserFlair.java b/app/src/main/java/ml/docilealligator/infinityforreddit/UserFlair.java
new file mode 100644
index 00000000..1854ee89
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/UserFlair.java
@@ -0,0 +1,78 @@
+package ml.docilealligator.infinityforreddit;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class UserFlair implements Parcelable {
+ private String id;
+ private String text;
+ private String htmlText;
+ private boolean editable;
+ private int maxEmojis;
+
+ public UserFlair(String id, String text, String htmlText, boolean editable, int maxEmojis) {
+ this.id = id;
+ this.text = text;
+ this.htmlText = htmlText;
+ this.editable = editable;
+ this.maxEmojis = maxEmojis;
+ }
+
+ protected UserFlair(Parcel in) {
+ id = in.readString();
+ text = in.readString();
+ htmlText = in.readString();
+ editable = in.readByte() != 0;
+ maxEmojis = in.readInt();
+ }
+
+ public static final Creator<UserFlair> CREATOR = new Creator<UserFlair>() {
+ @Override
+ public UserFlair createFromParcel(Parcel in) {
+ return new UserFlair(in);
+ }
+
+ @Override
+ public UserFlair[] newArray(int size) {
+ return new UserFlair[size];
+ }
+ };
+
+ public String getId() {
+ return id;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ public String getHtmlText() {
+ return htmlText;
+ }
+
+ public boolean isEditable() {
+ return editable;
+ }
+
+ public int getMaxEmojis() {
+ return maxEmojis;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int i) {
+ parcel.writeString(id);
+ parcel.writeString(text);
+ parcel.writeString(htmlText);
+ parcel.writeByte((byte) (editable ? 1 : 0));
+ parcel.writeInt(maxEmojis);
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/JSONUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/JSONUtils.java
index 1d9c876f..362d4b3f 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/JSONUtils.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/JSONUtils.java
@@ -123,4 +123,6 @@ public class JSONUtils {
public static final String Y_KEY = "y";
public static final String DEST_KEY = "dest";
public static final String GIF_KEY = "gif";
+ public static final String MAX_EMOJIS_KEY = "max_emojis";
+ public static final String RICHTEXT_KEY = "richtext";
}
diff --git a/app/src/main/res/drawable/ic_outline_edit_24px.xml b/app/src/main/res/drawable/ic_outline_edit_24px.xml
deleted file mode 100644
index 17a2a81f..00000000
--- a/app/src/main/res/drawable/ic_outline_edit_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M14.06,9.02l0.92,0.92L5.92,19L5,19v-0.92l9.06,-9.06M17.66,3c-0.25,0 -0.51,0.1 -0.7,0.29l-1.83,1.83 3.75,3.75 1.83,-1.83c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.2,-0.2 -0.45,-0.29 -0.71,-0.29zM14.06,6.19L3,17.25L3,21h3.75L17.81,9.94l-3.75,-3.75z"/>
-</vector>
diff --git a/app/src/main/res/layout/activity_select_user_flair.xml b/app/src/main/res/layout/activity_select_user_flair.xml
new file mode 100644
index 00000000..40e3eb83
--- /dev/null
+++ b/app/src/main/res/layout/activity_select_user_flair.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/coordinator_layout_select_user_flair_activity"
+ tools:context=".Activity.SelectUserFlairActivity">
+
+ <com.google.android.material.appbar.AppBarLayout
+ android:id="@+id/appbar_layout_select_user_flair_activity"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:theme="@style/AppTheme.AppBarOverlay">
+
+ <androidx.appcompat.widget.Toolbar
+ android:id="@+id/toolbar_select_user_flair_activity"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?attr/actionBarSize"
+ app:navigationIcon="?attr/homeAsUpIndicator"
+ app:popupTheme="@style/AppTheme.PopupOverlay" />
+
+ </com.google.android.material.appbar.AppBarLayout>
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/recycler_view_select_user_flair_activity"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior" />
+
+</androidx.coordinatorlayout.widget.CoordinatorLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/item_flair.xml b/app/src/main/res/layout/item_flair.xml
index 9379800d..de10c3dd 100644
--- a/app/src/main/res/layout/item_flair.xml
+++ b/app/src/main/res/layout/item_flair.xml
@@ -22,10 +22,11 @@
android:layout_height="24dp"
android:layout_gravity="center_vertical|end"
android:layout_marginStart="32dp"
- android:src="@drawable/ic_outline_edit_24px"
+ android:src="@drawable/ic_edit_24dp"
android:visibility="gone"
app:tint="?attr/primaryTextColor"
android:background="?actionBarItemBackground"
android:clickable="true"
android:focusable="true" />
+
</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/item_user_flair.xml b/app/src/main/res/layout/item_user_flair.xml
new file mode 100644
index 00000000..e85daae8
--- /dev/null
+++ b/app/src/main/res/layout/item_user_flair.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?selectableItemBackground"
+ android:clickable="true"
+ android:focusable="true">
+
+ <TextView
+ android:id="@+id/user_flair_html_text_view_item_user_flair"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="16dp"
+ android:textColor="?attr/primaryTextColor"
+ android:textSize="?attr/font_default"
+ android:fontFamily="?attr/font_family" />
+
+ <ImageView
+ android:id="@+id/edit_user_flair_image_view_item_user_flair"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="32dp"
+ android:padding="16dp"
+ android:src="@drawable/ic_edit_24dp"
+ android:background="?actionBarItemBackground"
+ android:clickable="true"
+ android:focusable="true" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/menu/view_subreddit_detail_activity.xml b/app/src/main/res/menu/view_subreddit_detail_activity.xml
index daea0d09..67a7bf24 100644
--- a/app/src/main/res/menu/view_subreddit_detail_activity.xml
+++ b/app/src/main/res/menu/view_subreddit_detail_activity.xml
@@ -35,6 +35,12 @@
app:showAsAction="never" />
<item
+ android:id="@+id/action_select_user_flair_view_subreddit_detail_activity"
+ android:orderInCategory="6"
+ android:title="@string/action_select_user_flair"
+ app:showAsAction="never" />
+
+ <item
android:id="@+id/action_share_view_subreddit_detail_activity"
android:orderInCategory="7"
android:title="@string/action_share"
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 4087ee9f..6185b922 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -67,6 +67,7 @@
<string name="action_set_wallpaper">Set as Wallpaper</string>
<string name="action_send_private_message">Send Private Message</string>
<string name="action_block_user">Block User</string>
+ <string name="action_select_user_flair">Select User Flair</string>
<string name="parse_json_response_error">Error occurred when parsing the JSON response</string>
<string name="retrieve_token_error">Error Retrieving the token</string>
@@ -860,4 +861,8 @@
<string name="unlock_account_section">Unlock Account Section</string>
+ <string name="select_user_flair_success">User flair selected</string>
+ <string name="select_user_flair_failed">Cannot select user flair</string>
+ <string name="select_this_user_flair">Select this user flair?</string>
+
</resources>