Prevent UUID-only contacts from being added to GV1 groups.

master
Greyson Parrelli 2020-07-29 23:04:35 -04:00
parent cc84901a49
commit 550b121990
10 changed files with 94 additions and 33 deletions

View File

@ -113,7 +113,9 @@ public abstract class ContactSelectionActivity extends PassphraseRequiredActivit
}
@Override
public void onContactSelected(Optional<RecipientId> recipientId, String number) {}
public boolean onContactSelected(Optional<RecipientId> recipientId, String number) {
return true;
}
@Override
public void onContactDeselected(Optional<RecipientId> recipientId, String number) {}

View File

@ -473,11 +473,15 @@ public final class ContactSelectionListFragment extends LoggingFragment
if (uuid.isPresent()) {
Recipient recipient = Recipient.externalUsername(requireContext(), uuid.get(), contact.getNumber());
SelectedContact selected = SelectedContact.forUsername(recipient.getId(), contact.getNumber());
markContactSelected(selected);
cursorRecyclerViewAdapter.notifyItemChanged(recyclerView.getChildAdapterPosition(contact), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE);
if (onContactSelectedListener != null) {
onContactSelectedListener.onContactSelected(Optional.of(recipient.getId()), null);
if (onContactSelectedListener.onContactSelected(Optional.of(recipient.getId()), null)) {
markContactSelected(selected);
cursorRecyclerViewAdapter.notifyItemChanged(recyclerView.getChildAdapterPosition(contact), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE);
}
} else {
markContactSelected(selected);
cursorRecyclerViewAdapter.notifyItemChanged(recyclerView.getChildAdapterPosition(contact), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE);
}
} else {
new AlertDialog.Builder(requireContext())
@ -488,11 +492,14 @@ public final class ContactSelectionListFragment extends LoggingFragment
}
});
} else {
markContactSelected(selectedContact);
cursorRecyclerViewAdapter.notifyItemChanged(recyclerView.getChildAdapterPosition(contact), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE);
if (onContactSelectedListener != null) {
onContactSelectedListener.onContactSelected(contact.getRecipientId(), contact.getNumber());
if (onContactSelectedListener.onContactSelected(contact.getRecipientId(), contact.getNumber())) {
markContactSelected(selectedContact);
cursorRecyclerViewAdapter.notifyItemChanged(recyclerView.getChildAdapterPosition(contact), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE);
}
} else {
markContactSelected(selectedContact);
cursorRecyclerViewAdapter.notifyItemChanged(recyclerView.getChildAdapterPosition(contact), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE);
}
}
} else {
@ -624,7 +631,8 @@ public final class ContactSelectionListFragment extends LoggingFragment
}
public interface OnContactSelectedListener {
void onContactSelected(Optional<RecipientId> recipientId, String number);
/** @return True if the contact is allowed to be selected, otherwise false. */
boolean onContactSelected(Optional<RecipientId> recipientId, String number);
void onContactDeselected(Optional<RecipientId> recipientId, String number);
}

View File

@ -121,8 +121,9 @@ public class InviteActivity extends PassphraseRequiredActivity implements Contac
}
@Override
public void onContactSelected(Optional<RecipientId> recipientId, String number) {
public boolean onContactSelected(Optional<RecipientId> recipientId, String number) {
updateSmsButtonText();
return true;
}
@Override

View File

@ -60,7 +60,7 @@ public class NewConversationActivity extends ContactSelectionActivity
}
@Override
public void onContactSelected(Optional<RecipientId> recipientId, String number) {
public boolean onContactSelected(Optional<RecipientId> recipientId, String number) {
if (recipientId.isPresent()) {
launch(Recipient.resolved(recipientId.get()));
} else {
@ -92,6 +92,8 @@ public class NewConversationActivity extends ContactSelectionActivity
launch(Recipient.external(this, number));
}
}
return true;
}
private void launch(Recipient recipient) {

View File

@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.groups.ui.addmembers;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
@ -58,14 +59,19 @@ public class AddMembersActivity extends PushContactSelectionActivity {
}
@Override
public void onContactSelected(Optional<RecipientId> recipientId, String number) {
public boolean onContactSelected(Optional<RecipientId> recipientId, String number) {
if (getGroupId().isV1() && recipientId.isPresent() && !Recipient.resolved(recipientId.get()).hasE164()) {
Toast.makeText(this, R.string.AddMembersActivity__this_person_cant_be_added_to_legacy_groups, Toast.LENGTH_SHORT).show();
return false;
}
if (contactsFragment.hasQueryFilter()) {
getToolbar().clear();
}
if (contactsFragment.getSelectedContactsCount() >= 1) {
enableDone();
}
enableDone();
return true;
}
@Override

View File

@ -39,13 +39,18 @@ public final class AddToGroupViewModel extends ViewModel {
events.postValue(new Event.CloseEvent());
} else if (groupRecipientIds.size() == 1) {
SignalExecutors.BOUNDED.execute(() -> {
Recipient recipient = Recipient.resolved(recipientId);
Recipient groupRecipient = Recipient.resolved(groupRecipientIds.get(0));
String recipientName = Recipient.resolved(recipientId).getDisplayName(context);
String recipientName = recipient.getDisplayName(context);
String groupName = groupRecipient.getDisplayName(context);
events.postValue(new Event.AddToSingleGroupConfirmationEvent(context.getResources().getString(R.string.AddToGroupActivity_add_member),
context.getResources().getString(R.string.AddToGroupActivity_add_s_to_s, recipientName, groupName),
groupRecipient, recipientName, groupName));
if (groupRecipient.getGroupId().get().isV1() && !recipient.hasE164()) {
events.postValue(new Event.LegacyGroupDenialEvent());
} else {
events.postValue(new Event.AddToSingleGroupConfirmationEvent(context.getResources().getString(R.string.AddToGroupActivity_add_member),
context.getResources().getString(R.string.AddToGroupActivity_add_s_to_s, recipientName, groupName),
groupRecipient, recipientName, groupName));
}
});
} else {
throw new AssertionError("Does not support multi-select");
@ -107,6 +112,9 @@ public final class AddToGroupViewModel extends ViewModel {
return message;
}
}
static class LegacyGroupDenialEvent extends Event {
}
}
public static class Factory implements ViewModelProvider.Factory {

View File

@ -91,6 +91,8 @@ public final class AddToGroupsActivity extends ContactSelectionActivity {
.setPositiveButton(android.R.string.ok, (dialog, which) -> viewModel.onAddToGroupsConfirmed(addEvent))
.setNegativeButton(android.R.string.cancel, null)
.show();
} else if (event instanceof Event.LegacyGroupDenialEvent) {
Toast.makeText(this, R.string.AddToGroupActivity_this_person_cant_be_added_to_legacy_groups, Toast.LENGTH_SHORT).show();
} else {
throw new AssertionError();
}
@ -112,20 +114,23 @@ public final class AddToGroupsActivity extends ContactSelectionActivity {
}
@Override
public void onContactSelected(Optional<RecipientId> recipientId, String number) {
public boolean onContactSelected(Optional<RecipientId> recipientId, String number) {
if (contactsFragment.isMulti()) {
if (contactsFragment.hasQueryFilter()) {
getToolbar().clear();
}
if (contactsFragment.getSelectedContactsCount() >= MINIMUM_GROUP_SELECT_SIZE) {
enableNext();
}
throw new UnsupportedOperationException("Not yet built to handle multi-select.");
// if (contactsFragment.hasQueryFilter()) {
// getToolbar().clear();
// }
//
// if (contactsFragment.getSelectedContactsCount() >= MINIMUM_GROUP_SELECT_SIZE) {
// enableNext();
// }
} else {
if (recipientId.isPresent()) {
viewModel.onContinueWithSelection(Collections.singletonList(recipientId.get()));
}
}
return true;
}
@Override

View File

@ -8,6 +8,7 @@ import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import com.annimon.stream.Stream;
@ -30,6 +31,8 @@ import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
import org.whispersystems.libsignal.util.guava.Optional;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class CreateGroupActivity extends ContactSelectionActivity {
@ -90,14 +93,14 @@ public class CreateGroupActivity extends ContactSelectionActivity {
}
@Override
public void onContactSelected(Optional<RecipientId> recipientId, String number) {
public boolean onContactSelected(Optional<RecipientId> recipientId, String number) {
if (contactsFragment.hasQueryFilter()) {
getToolbar().clear();
}
if (contactsFragment.getSelectedContactsCount() >= MINIMUM_GROUP_SIZE) {
enableNext();
}
enableNext();
return true;
}
@Override
@ -160,13 +163,31 @@ public class CreateGroupActivity extends ContactSelectionActivity {
stopwatch.split("capabilities");
resolved = Recipient.resolvedList(ids);
if (Stream.of(resolved).anyMatch(r -> r.getGroupsV2Capability() != Recipient.Capability.SUPPORTED) &&
Stream.of(resolved).anyMatch(r -> !r.hasE164()))
{
Log.w(TAG, "Invalid GV1 group...");
ids = Collections.emptyList();
}
stopwatch.split("gv1-check");
return ids;
}, ids -> {
dismissibleDialog.dismiss();
stopwatch.stop(TAG);
startActivityForResult(AddGroupDetailsActivity.newIntent(this, ids), REQUEST_CODE_ADD_DETAILS);
if (ids.isEmpty()) {
new AlertDialog.Builder(this)
.setMessage(R.string.CreateGroupActivity_some_contacts_cannot_be_in_legacy_groups)
.setPositiveButton(android.R.string.ok, (d, w) -> d.dismiss())
.show();
} else {
startActivityForResult(AddGroupDetailsActivity.newIntent(this, ids), REQUEST_CODE_ADD_DETAILS);
}
});
}
}

View File

@ -148,8 +148,9 @@ public class ShareActivity extends PassphraseRequiredActivity
else super.onBackPressed();
}
@Override
public void onContactSelected(Optional<RecipientId> recipientId, String number) {
public boolean onContactSelected(Optional<RecipientId> recipientId, String number) {
SimpleTask.run(this.getLifecycle(), () -> {
Recipient recipient;
if (recipientId.isPresent()) {
@ -162,6 +163,8 @@ public class ShareActivity extends PassphraseRequiredActivity
long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient);
return new Pair<>(existingThread, recipient);
}, result -> onDestinationChosen(result.first(), result.second().getId()));
return true;
}
@Override

View File

@ -365,6 +365,9 @@
<string name="ConversationTitleView_verified">Verified</string>
<string name="ConversationTitleView_you">You</string>
<!-- CreateGroupActivity -->
<string name="CreateGroupActivity_some_contacts_cannot_be_in_legacy_groups">Some contacts cannot be in legacy groups.</string>
<!-- CreateProfileActivity -->
<string name="CreateProfileActivity__profile">Profile</string>
<string name="CreateProfileActivity_error_setting_profile_photo">Error setting profile photo</string>
@ -444,6 +447,7 @@
<string name="AddToGroupActivity_s_added_to_s">\"%1$s\" added to \"%2$s\".</string>
<string name="AddToGroupActivity_add_to_group">Add to group</string>
<string name="AddToGroupActivity_add_to_groups">Add to groups</string>
<string name="AddToGroupActivity_this_person_cant_be_added_to_legacy_groups">This person can\'t be added to legacy groups.</string>
<!-- ChooseNewAdminActivity -->
<string name="ChooseNewAdminActivity_choose_new_admin">Choose new admin</string>
@ -502,6 +506,7 @@
<!-- AddMembersActivity -->
<string name="AddMembersActivity__done">Done</string>
<string name="AddMembersActivity__this_person_cant_be_added_to_legacy_groups">This person can\'t be added to legacy groups.</string>
<plurals name="AddMembersActivity__add_d_members_to_s">
<item quantity="one">Add \"%1$s\" to \"%2$s\"?</item>
<item quantity="other">Add %3$d members to \"%2$s\"?</item>