mirror of
https://codeberg.org/Bazsalanszky/Infinity-For-Lemmy.git
synced 2024-11-07 11:17:25 +01:00
Select user flair in subreddits.
This commit is contained in:
parent
9979c91b3c
commit
a3367c193b
@ -26,7 +26,11 @@
|
|||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
tools:replace="android:label">
|
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:parentActivityName=".Activity.MainActivity"
|
||||||
android:theme="@style/AppTheme.Slidable" />
|
android:theme="@style/AppTheme.Slidable" />
|
||||||
<activity
|
<activity
|
||||||
|
@ -318,4 +318,12 @@ public interface RedditAPI {
|
|||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@POST("api/block_user")
|
@POST("api/block_user")
|
||||||
Call<String> blockUser(@HeaderMap Map<String, String> headers, @FieldMap Map<String, String> params);
|
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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -749,6 +749,15 @@ public class ViewSubredditDetailActivity extends BaseActivity implements SortTyp
|
|||||||
case R.id.action_change_post_layout_view_subreddit_detail_activity:
|
case R.id.action_change_post_layout_view_subreddit_detail_activity:
|
||||||
postLayoutBottomSheetFragment.show(getSupportFragmentManager(), postLayoutBottomSheetFragment.getTag());
|
postLayoutBottomSheetFragment.show(getSupportFragmentManager(), postLayoutBottomSheetFragment.getTag());
|
||||||
return true;
|
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:
|
case R.id.action_share_view_subreddit_detail_activity:
|
||||||
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||||
shareIntent.setType("text/plain");
|
shareIntent.setType("text/plain");
|
||||||
|
@ -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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -27,6 +27,7 @@ import ml.docilealligator.infinityforreddit.Activity.RulesActivity;
|
|||||||
import ml.docilealligator.infinityforreddit.Activity.SearchActivity;
|
import ml.docilealligator.infinityforreddit.Activity.SearchActivity;
|
||||||
import ml.docilealligator.infinityforreddit.Activity.SearchResultActivity;
|
import ml.docilealligator.infinityforreddit.Activity.SearchResultActivity;
|
||||||
import ml.docilealligator.infinityforreddit.Activity.SearchSubredditsResultActivity;
|
import ml.docilealligator.infinityforreddit.Activity.SearchSubredditsResultActivity;
|
||||||
|
import ml.docilealligator.infinityforreddit.Activity.SelectUserFlairActivity;
|
||||||
import ml.docilealligator.infinityforreddit.Activity.SelectedSubredditsActivity;
|
import ml.docilealligator.infinityforreddit.Activity.SelectedSubredditsActivity;
|
||||||
import ml.docilealligator.infinityforreddit.Activity.SendPrivateMessageActivity;
|
import ml.docilealligator.infinityforreddit.Activity.SendPrivateMessageActivity;
|
||||||
import ml.docilealligator.infinityforreddit.Activity.SettingsActivity;
|
import ml.docilealligator.infinityforreddit.Activity.SettingsActivity;
|
||||||
@ -200,4 +201,6 @@ public interface AppComponent {
|
|||||||
void inject(SubmitCrosspostActivity submitCrosspostActivity);
|
void inject(SubmitCrosspostActivity submitCrosspostActivity);
|
||||||
|
|
||||||
void inject(CommentFullMarkdownActivity commentFullMarkdownActivity);
|
void inject(CommentFullMarkdownActivity commentFullMarkdownActivity);
|
||||||
|
|
||||||
|
void inject(SelectUserFlairActivity selectUserFlairActivity);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -123,4 +123,6 @@ public class JSONUtils {
|
|||||||
public static final String Y_KEY = "y";
|
public static final String Y_KEY = "y";
|
||||||
public static final String DEST_KEY = "dest";
|
public static final String DEST_KEY = "dest";
|
||||||
public static final String GIF_KEY = "gif";
|
public static final String GIF_KEY = "gif";
|
||||||
|
public static final String MAX_EMOJIS_KEY = "max_emojis";
|
||||||
|
public static final String RICHTEXT_KEY = "richtext";
|
||||||
}
|
}
|
||||||
|
@ -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>
|
|
32
app/src/main/res/layout/activity_select_user_flair.xml
Normal file
32
app/src/main/res/layout/activity_select_user_flair.xml
Normal file
@ -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>
|
@ -22,10 +22,11 @@
|
|||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_gravity="center_vertical|end"
|
android:layout_gravity="center_vertical|end"
|
||||||
android:layout_marginStart="32dp"
|
android:layout_marginStart="32dp"
|
||||||
android:src="@drawable/ic_outline_edit_24px"
|
android:src="@drawable/ic_edit_24dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:tint="?attr/primaryTextColor"
|
app:tint="?attr/primaryTextColor"
|
||||||
android:background="?actionBarItemBackground"
|
android:background="?actionBarItemBackground"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true" />
|
android:focusable="true" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
32
app/src/main/res/layout/item_user_flair.xml
Normal file
32
app/src/main/res/layout/item_user_flair.xml
Normal file
@ -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>
|
@ -34,6 +34,12 @@
|
|||||||
android:title="@string/action_change_post_layout"
|
android:title="@string/action_change_post_layout"
|
||||||
app:showAsAction="never" />
|
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
|
<item
|
||||||
android:id="@+id/action_share_view_subreddit_detail_activity"
|
android:id="@+id/action_share_view_subreddit_detail_activity"
|
||||||
android:orderInCategory="7"
|
android:orderInCategory="7"
|
||||||
|
@ -67,6 +67,7 @@
|
|||||||
<string name="action_set_wallpaper">Set as Wallpaper</string>
|
<string name="action_set_wallpaper">Set as Wallpaper</string>
|
||||||
<string name="action_send_private_message">Send Private Message</string>
|
<string name="action_send_private_message">Send Private Message</string>
|
||||||
<string name="action_block_user">Block User</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="parse_json_response_error">Error occurred when parsing the JSON response</string>
|
||||||
<string name="retrieve_token_error">Error Retrieving the token</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="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>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user