mirror of
https://github.com/oxen-io/session-android.git
synced 2025-06-08 22:48:34 +00:00
Fix contact selection behavior when searching and clear search on selection.
This commit is contained in:
parent
ae87d23003
commit
7f2439f1e9
@ -44,6 +44,7 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.content.Loader;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
@ -195,6 +196,12 @@ public final class ContactSelectionListFragment extends Fragment
|
||||
constraintLayout = view.findViewById(R.id.container);
|
||||
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||
recyclerView.setItemAnimator(new DefaultItemAnimator() {
|
||||
@Override
|
||||
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
swipeRefresh.setEnabled(requireActivity().getIntent().getBooleanExtra(REFRESHABLE, true));
|
||||
|
||||
@ -335,6 +342,10 @@ public final class ContactSelectionListFragment extends Fragment
|
||||
swipeRefresh.setRefreshing(false);
|
||||
}
|
||||
|
||||
public boolean hasQueryFilter() {
|
||||
return !TextUtils.isEmpty(cursorFilter);
|
||||
}
|
||||
|
||||
public void setRefreshing(boolean refreshing) {
|
||||
swipeRefresh.setRefreshing(refreshing);
|
||||
}
|
||||
@ -455,7 +466,8 @@ public final class ContactSelectionListFragment extends Fragment
|
||||
if (uuid.isPresent()) {
|
||||
Recipient recipient = Recipient.externalUsername(requireContext(), uuid.get(), contact.getNumber());
|
||||
SelectedContact selected = SelectedContact.forUsername(recipient.getId(), contact.getNumber());
|
||||
markContactSelected(selected, contact);
|
||||
markContactSelected(selected);
|
||||
cursorRecyclerViewAdapter.notifyItemChanged(recyclerView.getChildAdapterPosition(contact), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE);
|
||||
|
||||
if (onContactSelectedListener != null) {
|
||||
onContactSelectedListener.onContactSelected(Optional.of(recipient.getId()), null);
|
||||
@ -469,14 +481,16 @@ public final class ContactSelectionListFragment extends Fragment
|
||||
}
|
||||
});
|
||||
} else {
|
||||
markContactSelected(selectedContact, contact);
|
||||
markContactSelected(selectedContact);
|
||||
cursorRecyclerViewAdapter.notifyItemChanged(recyclerView.getChildAdapterPosition(contact), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE);
|
||||
|
||||
if (onContactSelectedListener != null) {
|
||||
onContactSelectedListener.onContactSelected(contact.getRecipientId(), contact.getNumber());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
markContactUnselected(selectedContact, contact);
|
||||
markContactUnselected(selectedContact);
|
||||
cursorRecyclerViewAdapter.notifyItemChanged(recyclerView.getChildAdapterPosition(contact), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE);
|
||||
|
||||
if (onContactSelectedListener != null) {
|
||||
onContactSelectedListener.onContactDeselected(contact.getRecipientId(), contact.getNumber());
|
||||
@ -488,17 +502,16 @@ public final class ContactSelectionListFragment extends Fragment
|
||||
return getChipCount() >= selectionLimit;
|
||||
}
|
||||
|
||||
private void markContactSelected(@NonNull SelectedContact selectedContact, @NonNull ContactSelectionListItem listItem) {
|
||||
private void markContactSelected(@NonNull SelectedContact selectedContact) {
|
||||
cursorRecyclerViewAdapter.addSelectedContact(selectedContact);
|
||||
listItem.setChecked(true);
|
||||
if (isMulti() && FeatureFlags.newGroupUI()) {
|
||||
addChipForContact(listItem, selectedContact);
|
||||
addChipForSelectedContact(selectedContact);
|
||||
}
|
||||
}
|
||||
|
||||
private void markContactUnselected(@NonNull SelectedContact selectedContact, @NonNull ContactSelectionListItem listItem) {
|
||||
private void markContactUnselected(@NonNull SelectedContact selectedContact) {
|
||||
cursorRecyclerViewAdapter.removeFromSelectedContacts(selectedContact);
|
||||
listItem.setChecked(false);
|
||||
cursorRecyclerViewAdapter.notifyItemRangeChanged(0, cursorRecyclerViewAdapter.getItemCount(), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE);
|
||||
removeChipForContact(selectedContact);
|
||||
}
|
||||
|
||||
@ -517,17 +530,23 @@ public final class ContactSelectionListFragment extends Fragment
|
||||
}
|
||||
}
|
||||
|
||||
private void addChipForContact(@NonNull ContactSelectionListItem contact, @NonNull SelectedContact selectedContact) {
|
||||
private void addChipForSelectedContact(@NonNull SelectedContact selectedContact) {
|
||||
SimpleTask.run(getViewLifecycleOwner().getLifecycle(),
|
||||
() -> Recipient.resolved(selectedContact.getOrCreateRecipientId(requireContext())),
|
||||
resolved -> addChipForRecipient(resolved, selectedContact));
|
||||
}
|
||||
|
||||
private void addChipForRecipient(@NonNull Recipient recipient, @NonNull SelectedContact selectedContact) {
|
||||
final ContactChip chip = new ContactChip(requireContext());
|
||||
|
||||
if (getChipCount() == 0) {
|
||||
setChipGroupVisibility(ConstraintSet.VISIBLE);
|
||||
}
|
||||
|
||||
chip.setText(contact.getChipName());
|
||||
chip.setText(recipient.getShortDisplayName(requireContext()));
|
||||
chip.setContact(selectedContact);
|
||||
chip.setCloseIconVisible(true);
|
||||
chip.setOnCloseIconClickListener(view -> markContactUnselected(selectedContact, contact));
|
||||
chip.setOnCloseIconClickListener(view -> markContactUnselected(selectedContact));
|
||||
|
||||
chipGroup.getLayoutTransition().addTransitionListener(new LayoutTransition.TransitionListener() {
|
||||
@Override
|
||||
@ -538,18 +557,13 @@ public final class ContactSelectionListFragment extends Fragment
|
||||
public void endTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {
|
||||
if (view == chip && transitionType == LayoutTransition.APPEARING) {
|
||||
chipGroup.getLayoutTransition().removeTransitionListener(this);
|
||||
registerChipRecipientObserver(chip, contact.getRecipient());
|
||||
registerChipRecipientObserver(chip, recipient.live());
|
||||
chipGroup.post(ContactSelectionListFragment.this::smoothScrollChipsToEnd);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
LiveRecipient recipient = contact.getRecipient();
|
||||
if (recipient != null) {
|
||||
chip.setAvatar(glideRequests, recipient.get(), () -> addChip(chip));
|
||||
} else {
|
||||
addChip(chip);
|
||||
}
|
||||
chip.setAvatar(glideRequests, recipient, () -> addChip(chip));
|
||||
}
|
||||
|
||||
private void addChip(@NonNull ContactChip chip) {
|
||||
|
@ -64,6 +64,8 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
|
||||
private final static int STYLE_ATTRIBUTES[] = new int[]{R.attr.contact_selection_push_user,
|
||||
R.attr.contact_selection_lay_user};
|
||||
|
||||
public static final int PAYLOAD_SELECTION_CHANGE = 1;
|
||||
|
||||
private final boolean multiSelect;
|
||||
private final LayoutInflater li;
|
||||
private final TypedArray drawables;
|
||||
@ -175,6 +177,7 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
|
||||
@Override
|
||||
public long getHeaderId(int i) {
|
||||
if (!isActiveCursor()) return -1;
|
||||
else if (i == -1) return -1;
|
||||
|
||||
int contactType = getContactType(i);
|
||||
|
||||
@ -216,6 +219,24 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindItemViewHolder(ViewHolder viewHolder, @NonNull Cursor cursor, @NonNull List<Object> payloads) {
|
||||
if (!arePayloadsValid(payloads)) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
String rawId = cursor.getString(cursor.getColumnIndexOrThrow(ContactRepository.ID_COLUMN));
|
||||
RecipientId id = rawId != null ? RecipientId.from(rawId) : null;
|
||||
int numberType = cursor.getInt(cursor.getColumnIndexOrThrow(ContactRepository.NUMBER_TYPE_COLUMN));
|
||||
String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactRepository.NUMBER_COLUMN));
|
||||
|
||||
if (numberType == ContactRepository.NEW_USERNAME_TYPE) {
|
||||
viewHolder.setChecked(selectedContacts.contains(SelectedContact.forUsername(id, number)));
|
||||
} else {
|
||||
viewHolder.setChecked(selectedContacts.contains(SelectedContact.forPhone(id, number)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(@NonNull Cursor cursor) {
|
||||
if (cursor.getInt(cursor.getColumnIndexOrThrow(ContactRepository.CONTACT_TYPE_COLUMN)) == ContactRepository.DIVIDER_TYPE) {
|
||||
@ -225,7 +246,6 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HeaderViewHolder onCreateHeaderViewHolder(ViewGroup parent, int position) {
|
||||
return new HeaderViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.contact_selection_recyclerview_header, parent, false));
|
||||
@ -236,6 +256,11 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
|
||||
((TextView)viewHolder.itemView).setText(getSpannedHeaderString(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean arePayloadsValid(@NonNull List<Object> payloads) {
|
||||
return payloads.size() == 1 && payloads.get(0).equals(PAYLOAD_SELECTION_CHANGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemViewRecycled(ViewHolder holder) {
|
||||
holder.unbind(glideRequests);
|
||||
|
@ -31,6 +31,8 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* RecyclerView.Adapter that manages a Cursor, comparable to the CursorAdapter usable in ListView/GridView.
|
||||
*/
|
||||
@ -173,6 +175,16 @@ public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHold
|
||||
|
||||
public abstract VH onCreateItemViewHolder(ViewGroup parent, int viewType);
|
||||
|
||||
@Override
|
||||
public final void onBindViewHolder(@NonNull ViewHolder viewHolder, int position, @NonNull List<Object> payloads) {
|
||||
if (arePayloadsValid(payloads) && !isHeaderPosition(position) && !isFooterPosition(position)) {
|
||||
if (isFastAccessPosition(position)) onBindFastAccessItemViewHolder((VH)viewHolder, position, payloads);
|
||||
else onBindItemViewHolder((VH)viewHolder, getCursorAtPositionOrThrow(position), payloads);
|
||||
} else {
|
||||
onBindViewHolder(viewHolder, position);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public final void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
|
||||
@ -188,8 +200,17 @@ public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHold
|
||||
|
||||
public abstract void onBindItemViewHolder(VH viewHolder, @NonNull Cursor cursor);
|
||||
|
||||
protected void onBindFastAccessItemViewHolder(VH viewHolder, int position) {
|
||||
protected boolean arePayloadsValid(@NonNull List<Object> payloads) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void onBindItemViewHolder(VH viewHolder, @NonNull Cursor cursor, @NonNull List<Object> payloads) {
|
||||
}
|
||||
|
||||
protected void onBindFastAccessItemViewHolder(VH viewHolder, int position) {
|
||||
}
|
||||
|
||||
protected void onBindFastAccessItemViewHolder(VH viewHolder, int position, @NonNull List<Object> payloads) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -82,6 +82,10 @@ public class CreateGroupActivity extends ContactSelectionActivity {
|
||||
|
||||
@Override
|
||||
public void onContactSelected(Optional<RecipientId> recipientId, String number) {
|
||||
if (contactsFragment.hasQueryFilter()) {
|
||||
getToolbar().clear();
|
||||
}
|
||||
|
||||
if (contactsFragment.getSelectedContactsCount() >= MINIMUM_GROUP_SIZE) {
|
||||
enableNext();
|
||||
}
|
||||
@ -89,6 +93,10 @@ public class CreateGroupActivity extends ContactSelectionActivity {
|
||||
|
||||
@Override
|
||||
public void onContactDeselected(Optional<RecipientId> recipientId, String number) {
|
||||
if (contactsFragment.hasQueryFilter()) {
|
||||
getToolbar().clear();
|
||||
}
|
||||
|
||||
if (contactsFragment.getSelectedContactsCount() < MINIMUM_GROUP_SIZE) {
|
||||
disableNext();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user