Fix chip jank and other groups v2 ux issues.

This commit is contained in:
Alex Hart
2020-05-27 12:19:20 -03:00
committed by Greyson Parrelli
parent 00996f0d7a
commit 903c3989b9
10 changed files with 120 additions and 151 deletions

View File

@@ -35,8 +35,7 @@ public abstract class GroupMemberEntry {
public final static class NewGroupCandidate extends GroupMemberEntry {
private final DefaultValueLiveData<Boolean> isSelected = new DefaultValueLiveData<>(false);
private final Recipient member;
private final Recipient member;
public NewGroupCandidate(@NonNull Recipient member) {
this.member = member;
@@ -46,14 +45,6 @@ public abstract class GroupMemberEntry {
return member;
}
public @NonNull LiveData<Boolean> isSelected() {
return isSelected;
}
public void setSelected(boolean isSelected) {
this.isSelected.postValue(isSelected);
}
@Override
boolean sameId(@NonNull GroupMemberEntry newItem) {
if (getClass() != newItem.getClass()) return false;

View File

@@ -246,9 +246,6 @@ final class GroupMemberListAdapter extends LifecycleRecyclerAdapter<GroupMemberL
bindRecipient(newGroupCandidate.getMember());
bindRecipientClick(newGroupCandidate.getMember());
itemView.setSelected(false);
newGroupCandidate.isSelected().observe(this, itemView::setSelected);
int smsWarningVisibility = newGroupCandidate.getMember().isRegistered() ? View.GONE : View.VISIBLE;
smsContact.setVisibility(smsWarningVisibility);

View File

@@ -20,6 +20,7 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProviders;
@@ -58,38 +59,6 @@ public class AddGroupDetailsFragment extends Fragment {
private Drawable avatarPlaceholder;
private EditText name;
private Toolbar toolbar;
private ActionMode actionMode;
private ActionMode.Callback recipientActionModeCallback = new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.add_group_details_fragment_context_menu, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
if (item.getItemId() == R.id.action_delete) {
viewModel.deleteSelected();
mode.finish();
return true;
}
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
actionMode = null;
viewModel.clearSelected();
}
};
@Override
public void onAttach(@NonNull Context context) {
@@ -142,7 +111,6 @@ public class AddGroupDetailsFragment extends Fragment {
avatar.setOnClickListener(v -> AvatarSelectionBottomSheetDialogFragment.create(viewModel.hasAvatar(), true, REQUEST_CODE_AVATAR, true)
.show(getChildFragmentManager(), "BOTTOM"));
members.setRecipientLongClickListener(this::handleRecipientLongClick);
members.setRecipientClickListener(this::handleRecipientClick);
name.addTextChangedListener(new AfterTextChanged(editable -> viewModel.setName(editable.toString())));
toolbar.setNavigationOnClickListener(unused -> callback.onNavigationButtonPressed());
@@ -219,29 +187,15 @@ public class AddGroupDetailsFragment extends Fragment {
}
private void handleRecipientClick(@NonNull Recipient recipient) {
if (actionMode == null) {
return;
}
int size = viewModel.toggleSelected(recipient);
if (size == 0) {
actionMode.finish();
}
}
private boolean handleRecipientLongClick(@NonNull Recipient recipient) {
if (actionMode != null) {
return false;
}
actionMode = toolbar.startActionMode(recipientActionModeCallback);
if (actionMode != null) {
viewModel.toggleSelected(recipient);
return true;
}
return false;
new AlertDialog.Builder(requireContext())
.setMessage(getString(R.string.AddGroupDetailsFragment__remove_s_from_this_group, recipient.getDisplayName(requireContext())))
.setCancelable(true)
.setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.cancel())
.setPositiveButton(R.string.AddGroupDetailsFragment__remove, (dialog, which) -> {
viewModel.delete(recipient.getId());
dialog.dismiss();
})
.show();
}
private void handleGroupCreateResult(@NonNull GroupCreateResult groupCreateResult) {

View File

@@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.DefaultValueLiveData;
import org.thoughtcrime.securesms.util.SingleLiveEvent;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
import java.util.HashSet;
@@ -28,7 +29,6 @@ import java.util.Set;
public final class AddGroupDetailsViewModel extends ViewModel {
private final LiveData<List<GroupMemberEntry.NewGroupCandidate>> members;
private final DefaultValueLiveData<Set<RecipientId>> selected = new DefaultValueLiveData<>(new HashSet<>());
private final DefaultValueLiveData<Set<RecipientId>> deleted = new DefaultValueLiveData<>(new HashSet<>());
private final MutableLiveData<String> name = new MutableLiveData<>("");
private final MutableLiveData<byte[]> avatar = new MutableLiveData<>();
@@ -37,17 +37,14 @@ public final class AddGroupDetailsViewModel extends ViewModel {
private final LiveData<Boolean> canSubmitForm = Transformations.map(name, name -> !TextUtils.isEmpty(name));
private final AddGroupDetailsRepository repository;
AddGroupDetailsViewModel(@NonNull RecipientId[] recipientIds,
@NonNull AddGroupDetailsRepository repository)
private AddGroupDetailsViewModel(@NonNull RecipientId[] recipientIds,
@NonNull AddGroupDetailsRepository repository)
{
this.repository = repository;
MutableLiveData<List<GroupMemberEntry.NewGroupCandidate>> initialMembers = new MutableLiveData<>();
LiveData<List<GroupMemberEntry.NewGroupCandidate>> membersWithoutDeleted = LiveDataUtil.combineLatest(initialMembers,
deleted,
AddGroupDetailsViewModel::filterDeletedMembers);
MutableLiveData<List<GroupMemberEntry.NewGroupCandidate>> initialMembers = new MutableLiveData<>();
members = LiveDataUtil.combineLatest(membersWithoutDeleted, selected, AddGroupDetailsViewModel::updateSelectedMembers);
members = LiveDataUtil.combineLatest(initialMembers, deleted, AddGroupDetailsViewModel::filterDeletedMembers);
isMms = Transformations.map(members, this::isAnyForcedSms);
repository.resolveMembers(recipientIds, initialMembers::postValue);
@@ -85,27 +82,10 @@ public final class AddGroupDetailsViewModel extends ViewModel {
this.name.setValue(name);
}
int toggleSelected(@NonNull Recipient recipient) {
Set<RecipientId> selected = this.selected.getValue();
if (!selected.add(recipient.getId())) {
selected.remove(recipient.getId());
}
this.selected.setValue(selected);
return selected.size();
}
void clearSelected() {
this.selected.setValue(new HashSet<>());
}
void deleteSelected() {
Set<RecipientId> selected = this.selected.getValue();
void delete(@NonNull RecipientId recipientId) {
Set<RecipientId> deleted = this.deleted.getValue();
deleted.addAll(selected);
deleted.add(recipientId);
this.deleted.setValue(deleted);
}
@@ -139,14 +119,6 @@ public final class AddGroupDetailsViewModel extends ViewModel {
.toList();
}
private static @NonNull List<GroupMemberEntry.NewGroupCandidate> updateSelectedMembers(@NonNull List<GroupMemberEntry.NewGroupCandidate> members, @NonNull Set<RecipientId> selected) {
for (GroupMemberEntry.NewGroupCandidate member : members) {
member.setSelected(selected.contains(member.getMember().getId()));
}
return members;
}
private boolean isAnyForcedSms(@NonNull List<GroupMemberEntry.NewGroupCandidate> members) {
return Stream.of(members)
.anyMatch(member -> !member.getMember().isRegistered());