Multi-selection in user search result for CustomizePostFilterActivity.

This commit is contained in:
Alex Ning 2021-02-26 12:26:21 +08:00
parent b86e5284a2
commit e0106e23e5
11 changed files with 176 additions and 61 deletions

View File

@ -247,6 +247,7 @@ public class CustomizePostFilterActivity extends BaseActivity {
addUsersImageView.setOnClickListener(view -> {
Intent intent = new Intent(this, SearchActivity.class);
intent.putExtra(SearchActivity.EXTRA_SEARCH_ONLY_USERS, true);
intent.putExtra(SearchActivity.EXTRA_IS_MULTI_SELECTION, true);
startActivityForResult(intent, ADD_USERS_REQUEST_CODE);
});
@ -423,28 +424,35 @@ public class CustomizePostFilterActivity extends BaseActivity {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && data != null) {
if (requestCode == ADD_SUBREDDITS_REQUEST_CODE) {
ArrayList<String> subreddits = data.getStringArrayListExtra(SubredditMultiselectionActivity.EXTRA_RETURN_SELECTED_SUBREDDITS);
ArrayList<String> subredditNames = data.getStringArrayListExtra(SubredditMultiselectionActivity.EXTRA_RETURN_SELECTED_SUBREDDITS);
String currentSubreddits = excludesSubredditsTextInputEditText.getText().toString().trim();
if (!currentSubreddits.isEmpty() && currentSubreddits.charAt(currentSubreddits.length() - 1) != ',') {
if (subredditNames != null && !currentSubreddits.isEmpty() && currentSubreddits.charAt(currentSubreddits.length() - 1) != ',') {
String newString = currentSubreddits + ",";
excludesSubredditsTextInputEditText.setText(newString);
}
if (subreddits != null) {
if (subredditNames != null) {
StringBuilder stringBuilder = new StringBuilder();
for (String s : subreddits) {
for (String s : subredditNames) {
stringBuilder.append(s).append(",");
}
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
excludesSubredditsTextInputEditText.append(stringBuilder.toString());
}
} else if (requestCode == ADD_USERS_REQUEST_CODE) {
String username = data.getStringExtra(SearchActivity.EXTRA_RETURN_USER_NAME);
String currentUsers = excludesSubredditsTextInputEditText.getText().toString().trim();
if (!currentUsers.isEmpty() && currentUsers.charAt(currentUsers.length() - 1) != ',') {
ArrayList<String> usernames = data.getStringArrayListExtra(SearchActivity.RETURN_EXTRA_SELECTED_USERNAMES);
String currentUsers = excludesUsersTextInputEditText.getText().toString().trim();
if (usernames != null && !currentUsers.isEmpty() && currentUsers.charAt(currentUsers.length() - 1) != ',') {
String newString = currentUsers + ",";
excludesSubredditsTextInputEditText.setText(newString);
excludesUsersTextInputEditText.setText(newString);
}
if (usernames != null) {
StringBuilder stringBuilder = new StringBuilder();
for (String s : usernames) {
stringBuilder.append(s).append(",");
}
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
excludesUsersTextInputEditText.append(stringBuilder.toString());
}
excludesUsersTextInputEditText.append(username);
}
}
}

View File

@ -54,6 +54,7 @@ public class SearchActivity extends BaseActivity {
static final String EXTRA_RETURN_SUBREDDIT_NAME = "ERSN";
static final String EXTRA_RETURN_SUBREDDIT_ICON_URL = "ERSIU";
static final String RETURN_EXTRA_SELECTED_SUBREDDIT_NAMES = "RESSN";
static final String RETURN_EXTRA_SELECTED_USERNAMES = "RESU";
static final String EXTRA_RETURN_USER_NAME = "ERUN";
static final String EXTRA_RETURN_USER_ICON_URL = "ERUIU";
static final String EXTRA_IS_MULTI_SELECTION = "EIMS";
@ -256,6 +257,7 @@ public class SearchActivity extends BaseActivity {
} else if (searchOnlyUsers) {
Intent intent = new Intent(this, SearchUsersResultActivity.class);
intent.putExtra(SearchUsersResultActivity.EXTRA_QUERY, query);
intent.putExtra(SearchUsersResultActivity.EXTRA_IS_MULTI_SELECTION, getIntent().getBooleanExtra(EXTRA_IS_MULTI_SELECTION, false));
startActivityForResult(intent, USER_SEARCH_REQUEST_CODE);
} else {
Intent intent = new Intent(SearchActivity.this, SearchResultActivity.class);
@ -355,11 +357,15 @@ public class SearchActivity extends BaseActivity {
setResult(Activity.RESULT_OK, returnIntent);
finish();
} else if (requestCode == USER_SEARCH_REQUEST_CODE) {
Intent returnIntent = new Intent();
if (getIntent().getBooleanExtra(EXTRA_IS_MULTI_SELECTION, false)) {
returnIntent.putStringArrayListExtra(RETURN_EXTRA_SELECTED_USERNAMES, data.getStringArrayListExtra(SearchUsersResultActivity.RETURN_EXTRA_SELECTED_USERNAMES));
} else {
String username = data.getStringExtra(SearchUsersResultActivity.EXTRA_RETURN_USER_NAME);
String iconUrl = data.getStringExtra(SearchUsersResultActivity.EXTRA_RETURN_USER_ICON_URL);
Intent returnIntent = new Intent();
returnIntent.putExtra(EXTRA_RETURN_USER_NAME, username);
returnIntent.putExtra(EXTRA_RETURN_USER_ICON_URL, iconUrl);
}
setResult(Activity.RESULT_OK, returnIntent);
finish();
}

View File

@ -169,13 +169,9 @@ public class SearchSubredditsResultActivity extends BaseActivity implements Acti
return true;
} else if (item.getItemId() == R.id.action_save_search_subreddits_result_activity) {
if (mFragment != null) {
List<SubredditData> subreddits = ((SubredditListingFragment) mFragment).getSelectedSubreddits();
ArrayList<String> subredditNames = new ArrayList<>();
for (SubredditData s : subreddits) {
subredditNames.add(s.getName());
}
ArrayList<String> selectedSubredditNames = ((SubredditListingFragment) mFragment).getSelectedSubredditNames();
Intent returnIntent = new Intent();
returnIntent.putStringArrayListExtra(RETURN_EXTRA_SELECTED_SUBREDDIT_NAMES, subredditNames);
returnIntent.putStringArrayListExtra(RETURN_EXTRA_SELECTED_SUBREDDIT_NAMES, selectedSubredditNames);
setResult(Activity.RESULT_OK, returnIntent);
finish();
}

View File

@ -5,6 +5,8 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
@ -20,6 +22,8 @@ import com.r0adkll.slidr.Slidr;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.util.ArrayList;
import javax.inject.Inject;
import javax.inject.Named;
@ -36,8 +40,10 @@ import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
public class SearchUsersResultActivity extends BaseActivity implements ActivityToolbarInterface {
static final String EXTRA_QUERY = "EQ";
static final String EXTRA_IS_MULTI_SELECTION = "EIMS";
static final String EXTRA_RETURN_USER_NAME = "ERUN";
static final String EXTRA_RETURN_USER_ICON_URL = "ERUIU";
static final String RETURN_EXTRA_SELECTED_USERNAMES = "RESU";
private static final String FRAGMENT_OUT_STATE = "FOS";
@ -111,6 +117,7 @@ public class SearchUsersResultActivity extends BaseActivity implements ActivityT
bundle.putBoolean(UserListingFragment.EXTRA_IS_GETTING_USER_INFO, true);
bundle.putString(UserListingFragment.EXTRA_ACCESS_TOKEN, mAccessToken);
bundle.putString(UserListingFragment.EXTRA_ACCOUNT_NAME, mAccountName);
bundle.putBoolean(UserListingFragment.EXTRA_IS_MULTI_SELECTION, getIntent().getBooleanExtra(EXTRA_IS_MULTI_SELECTION, false));
mFragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_search_users_result_activity, mFragment).commit();
} else {
@ -143,6 +150,33 @@ public class SearchUsersResultActivity extends BaseActivity implements ActivityT
finish();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (getIntent().getBooleanExtra(EXTRA_IS_MULTI_SELECTION, false)) {
getMenuInflater().inflate(R.menu.search_users_result_activity, menu);
applyMenuItemTheme(menu);
}
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
} else if (item.getItemId() == R.id.action_save_search_users_result_activity) {
if (mFragment != null) {
ArrayList<String> selectedUsernames = ((UserListingFragment) mFragment).getSelectedUsernames();
Intent returnIntent = new Intent();
returnIntent.putStringArrayListExtra(RETURN_EXTRA_SELECTED_USERNAMES, selectedUsernames);
setResult(Activity.RESULT_OK, returnIntent);
finish();
}
return true;
}
return false;
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);

View File

@ -22,6 +22,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import com.bumptech.glide.request.RequestOptions;
import com.google.android.material.checkbox.MaterialCheckBox;
import java.util.concurrent.Executor;
@ -61,6 +62,7 @@ public class UserListingRecyclerViewAdapter extends PagedListAdapter<UserData, R
private String accessToken;
private String accountName;
private RedditDataRoomDatabase redditDataRoomDatabase;
private boolean isMultiSelection;
private int primaryTextColor;
private int buttonTextColor;
@ -74,7 +76,7 @@ public class UserListingRecyclerViewAdapter extends PagedListAdapter<UserData, R
public UserListingRecyclerViewAdapter(Context context, Executor executor, Retrofit oauthRetrofit, Retrofit retrofit,
CustomThemeWrapper customThemeWrapper, String accessToken,
String accountName, RedditDataRoomDatabase redditDataRoomDatabase,
Callback callback) {
boolean isMultiSelection, Callback callback) {
super(DIFF_CALLBACK);
this.context = context;
this.executor = executor;
@ -83,6 +85,7 @@ public class UserListingRecyclerViewAdapter extends PagedListAdapter<UserData, R
this.accessToken = accessToken;
this.accountName = accountName;
this.redditDataRoomDatabase = redditDataRoomDatabase;
this.isMultiSelection = isMultiSelection;
this.callback = callback;
glide = Glide.with(context);
primaryTextColor = customThemeWrapper.getPrimaryTextColor();
@ -97,7 +100,7 @@ public class UserListingRecyclerViewAdapter extends PagedListAdapter<UserData, R
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_DATA) {
ConstraintLayout constraintLayout = (ConstraintLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_user_listing, parent, false);
return new UserListingRecyclerViewAdapter.DataViewHolder(constraintLayout);
return new DataViewHolder(constraintLayout);
} else if (viewType == VIEW_TYPE_ERROR) {
RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_error, parent, false);
return new UserListingRecyclerViewAdapter.ErrorViewHolder(relativeLayout);
@ -109,11 +112,15 @@ public class UserListingRecyclerViewAdapter extends PagedListAdapter<UserData, R
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder instanceof UserListingRecyclerViewAdapter.DataViewHolder) {
if (holder instanceof DataViewHolder) {
UserData userData = getItem(position);
if (userData != null) {
((UserListingRecyclerViewAdapter.DataViewHolder) holder).constraintLayout.setOnClickListener(view -> {
((DataViewHolder) holder).constraintLayout.setOnClickListener(view -> {
if (isMultiSelection) {
((DataViewHolder) holder).checkBox.performClick();
} else {
callback.userSelected(userData.getName(), userData.getIconUrl());
}
});
if (!userData.getIconUrl().equals("")) {
@ -121,32 +128,33 @@ public class UserListingRecyclerViewAdapter extends PagedListAdapter<UserData, R
.apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
.error(glide.load(R.drawable.subreddit_default_icon)
.apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))))
.into(((UserListingRecyclerViewAdapter.DataViewHolder) holder).iconGifImageView);
.into(((DataViewHolder) holder).iconGifImageView);
} else {
glide.load(R.drawable.subreddit_default_icon)
.apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
.into(((UserListingRecyclerViewAdapter.DataViewHolder) holder).iconGifImageView);
.into(((DataViewHolder) holder).iconGifImageView);
}
((UserListingRecyclerViewAdapter.DataViewHolder) holder).userNameTextView.setText(userData.getName());
((DataViewHolder) holder).userNameTextView.setText(userData.getName());
if (!isMultiSelection) {
CheckIsFollowingUser.checkIsFollowingUser(executor, new Handler(), redditDataRoomDatabase,
userData.getName(), accountName, new CheckIsFollowingUser.CheckIsFollowingUserListener() {
@Override
public void isSubscribed() {
((UserListingRecyclerViewAdapter.DataViewHolder) holder).subscribeButton.setVisibility(View.GONE);
((DataViewHolder) holder).subscribeButton.setVisibility(View.GONE);
}
@Override
public void isNotSubscribed() {
((UserListingRecyclerViewAdapter.DataViewHolder) holder).subscribeButton.setVisibility(View.VISIBLE);
((UserListingRecyclerViewAdapter.DataViewHolder) holder).subscribeButton.setOnClickListener(view -> {
((DataViewHolder) holder).subscribeButton.setVisibility(View.VISIBLE);
((DataViewHolder) holder).subscribeButton.setOnClickListener(view -> {
UserFollowing.followUser(oauthRetrofit, retrofit,
accessToken, userData.getName(), accountName, redditDataRoomDatabase,
new UserFollowing.UserFollowingListener() {
@Override
public void onUserFollowingSuccess() {
((UserListingRecyclerViewAdapter.DataViewHolder) holder).subscribeButton.setVisibility(View.GONE);
((DataViewHolder) holder).subscribeButton.setVisibility(View.GONE);
Toast.makeText(context, R.string.followed, Toast.LENGTH_SHORT).show();
}
@ -158,6 +166,9 @@ public class UserListingRecyclerViewAdapter extends PagedListAdapter<UserData, R
});
}
});
} else {
((DataViewHolder) holder).checkBox.setOnCheckedChangeListener((compoundButton, b) -> userData.setSelected(b));
}
}
}
}
@ -206,9 +217,9 @@ public class UserListingRecyclerViewAdapter extends PagedListAdapter<UserData, R
@Override
public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
if (holder instanceof UserListingRecyclerViewAdapter.DataViewHolder) {
glide.clear(((UserListingRecyclerViewAdapter.DataViewHolder) holder).iconGifImageView);
((UserListingRecyclerViewAdapter.DataViewHolder) holder).subscribeButton.setVisibility(View.GONE);
if (holder instanceof DataViewHolder) {
glide.clear(((DataViewHolder) holder).iconGifImageView);
((DataViewHolder) holder).subscribeButton.setVisibility(View.GONE);
}
}
@ -227,12 +238,17 @@ public class UserListingRecyclerViewAdapter extends PagedListAdapter<UserData, R
TextView userNameTextView;
@BindView(R.id.subscribe_image_view_item_user_listing)
ImageView subscribeButton;
@BindView(R.id.checkbox__item_user_listing)
MaterialCheckBox checkBox;
DataViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
userNameTextView.setTextColor(primaryTextColor);
subscribeButton.setColorFilter(unsubscribedColor, android.graphics.PorterDuff.Mode.SRC_IN);
if (isMultiSelection) {
checkBox.setVisibility(View.VISIBLE);
}
}
}

View File

@ -260,17 +260,17 @@ public class SubredditListingFragment extends Fragment implements FragmentCommun
return sortType;
}
public List<SubredditData> getSelectedSubreddits() {
public ArrayList<String> getSelectedSubredditNames() {
if (mSubredditListingViewModel != null) {
List<SubredditData> allSubreddits = mSubredditListingViewModel.getSubreddits().getValue();
if (allSubreddits == null) {
return null;
}
List<SubredditData> selectedSubreddits = new ArrayList<>();
ArrayList<String> selectedSubreddits = new ArrayList<>();
for (SubredditData s : allSubreddits) {
if (s.isSelected()) {
selectedSubreddits.add(s);
selectedSubreddits.add(s.getName());
}
}
return selectedSubreddits;

View File

@ -25,6 +25,8 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import javax.inject.Inject;
@ -35,8 +37,8 @@ import butterknife.ButterKnife;
import ml.docilealligator.infinityforreddit.FragmentCommunicator;
import ml.docilealligator.infinityforreddit.Infinity;
import ml.docilealligator.infinityforreddit.NetworkState;
import ml.docilealligator.infinityforreddit.RecyclerViewContentScrollingInterface;
import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.RecyclerViewContentScrollingInterface;
import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase;
import ml.docilealligator.infinityforreddit.SortType;
import ml.docilealligator.infinityforreddit.activities.BaseActivity;
@ -44,6 +46,7 @@ import ml.docilealligator.infinityforreddit.activities.SearchUsersResultActivity
import ml.docilealligator.infinityforreddit.activities.ViewUserDetailActivity;
import ml.docilealligator.infinityforreddit.adapters.UserListingRecyclerViewAdapter;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.user.UserData;
import ml.docilealligator.infinityforreddit.user.UserListingViewModel;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import retrofit2.Retrofit;
@ -56,6 +59,7 @@ public class UserListingFragment extends Fragment implements FragmentCommunicato
public static final String EXTRA_QUERY = "EQ";
public static final String EXTRA_IS_GETTING_USER_INFO = "EIGUI";
public static final String EXTRA_IS_MULTI_SELECTION = "EIMS";
public static final String EXTRA_ACCESS_TOKEN = "EAT";
public static final String EXTRA_ACCOUNT_NAME = "EAN";
@ -141,6 +145,7 @@ public class UserListingFragment extends Fragment implements FragmentCommunicato
mAdapter = new UserListingRecyclerViewAdapter(getActivity(), mExecutor, mOauthRetrofit, mRetrofit,
mCustomThemeWrapper, accessToken, accountName, mRedditDataRoomDatabase,
getArguments().getBoolean(EXTRA_IS_MULTI_SELECTION, false),
new UserListingRecyclerViewAdapter.Callback() {
@Override
public void retryLoadingMore() {
@ -256,4 +261,22 @@ public class UserListingFragment extends Fragment implements FragmentCommunicato
public SortType getSortType() {
return sortType;
}
public ArrayList<String> getSelectedUsernames() {
if (mUserListingViewModel != null) {
List<UserData> allUsers = mUserListingViewModel.getUsers().getValue();
if (allUsers != null) {
ArrayList<String> selectedUsernames = new ArrayList<>();
for (UserData u : allUsers) {
if (u.isSelected()) {
selectedUsernames.add(u.getName());
}
}
return selectedUsernames;
} else {
return null;
}
}
return null;
}
}

View File

@ -3,6 +3,7 @@ package ml.docilealligator.infinityforreddit.user;
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;
@Entity(tableName = "users")
@ -37,6 +38,8 @@ public class UserData {
private boolean isNSFW;
@ColumnInfo(name = "description")
private String description;
@Ignore
private boolean isSelected;
public UserData(@NonNull String name, String iconUrl, String banner, int linkKarma, int commentKarma,
int awarderKarma, int awardeeKarma, int totalKarma, long cakeday, boolean isGold,
@ -55,6 +58,7 @@ public class UserData {
this.canBeFollowed = canBeFollowed;
this.isNSFW = isNSFW;
this.description = description;
this.isSelected = false;
}
@NonNull
@ -113,4 +117,12 @@ public class UserData {
public String getDescription() {
return description;
}
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean selected) {
isSelected = selected;
}
}

View File

@ -50,6 +50,7 @@
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
app:layout_constraintBottom_toBottomOf="parent"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -44,4 +44,13 @@
android:background="?attr/selectableItemBackground"
android:visibility="gone" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/checkbox__item_user_listing"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_save_search_users_result_activity"
android:orderInCategory="1"
android:title="@string/action_save"
android:icon="@drawable/ic_check_circle_toolbar_24dp"
app:showAsAction="ifRoom" />
</menu>