diff options
author | Alex Ning <chineseperson5@gmail.com> | 2020-09-17 03:08:06 +0000 |
---|---|---|
committer | Alex Ning <chineseperson5@gmail.com> | 2020-09-17 03:08:06 +0000 |
commit | a3367c193b2b9f6e385c155e543debd9f2bb3426 (patch) | |
tree | 7d2f3307682a697225763aa6977ad050283c151e | |
parent | 9979c91b3cc58a13e72e84208d1b79f71ee0dc50 (diff) | |
download | infinity-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.
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> |